KMPEXKMP学习笔记
字符串匹配算法KMP
KMP是啥
一種基礎的字符串匹配算法,是學習字符串算法的基礎
很多人都是以這個算法為起點開始學習字符串的
KMP的作用
求出模式串在文本串里出現了多少次,以及在哪里出現過
KMP的實現
暴力
假如直接暴力匹配的話,復雜度\(O(nm)\)(n是模式串長度,m是文本串長度)
明顯T飛
于是我們就有了KMP算法
核心部分
先上定義部分:
int kmp[2000001];//kmp中的指針 char a[2000001],b[2000001];//a是文本串,b是模式串然后我們現在來看一看什么是kmp里面的kmp數組。
- kmp失配指針
這個失配指針就是上面的kmp數組了
這個kmp是什么意思呢?這個kmp[i]代表的是,在[1..i]這個子串中,前綴與后綴的最長長度
- kmp第一步:自配
首先定義前綴i代表子串[1..i],后綴i代表子串[j..len]
這其中的\(while(j&&b[i]!=b[j+1])\)是怎么回事兒呢?
首先我們要知道,j就是前綴i-1的前綴與后綴的最長相同長度
那么我們首先看一看目前走到的第i位與第j+1位相不相同
假如相同,那么前綴j+1就與后綴[i-j..i]相同了
假如不同,那么我們跳到下一個相同的地方。
然后不斷地沿著kmp跳,直到跳到相同的地方。假如沒有相同的,那這個kmp[i]就為0了。
如下圖所示:
那么這里的i為什么不能取1呢?
大家可以自己試一試,如果取1的話就死循環了
- kmp第二步 在原串中匹配
有關于\(while(j&&a[i]!=b[j+1])\),這就是說,我們現在匹配到的第i位與b中的第j+1位不符合的話,
我們就找到前綴j+1的前綴與后綴的最長相同長度,然后從已經匹配好的前綴跳到相同的后綴上
大概就是這幅圖:
kmp到這里就結束啦~
- 完整代碼(洛谷P3375 【模板】KMP字符串匹配)
- 復雜度
時間復雜度是\(O(n+m)\)的(這不比樸素算法快多了?)
跑起來飛快(huaji)
EXKMP(擴展KMP)
簡介
這個算法用來求一個串的每個后綴與另一個串的\(LCP\),即最長公共前綴
然而似乎與kmp沒有什么關系
有關于這個算法,我當時并沒有怎么學
而且貌似是一個邊緣算法,不怎么會考
所以貼個模板跑路吧
#include<bits/stdc++.h> using namespace std; int nxt[2000001]; int ext[2000001]; void pre(char s[]){int m=strlen(s);int j=0,p=0;nxt[0]=m;for(int i=1;i<m;++i){if(i>=p||i+nxt[i-j]>=p){if(i>=p)p=i;while(p<m&&s[p]==s[p-i])p++;nxt[i]=p-i;j=i;}else nxt[i]=nxt[i-j];}//for(int i=0;i<m;++i)printf("%d ",nxt[i]);//putchar('\n'); } void getext(char s[],char t[]){int n=strlen(s);int m=strlen(t);int j=0,p=0;pre(t);for(int i=0;i<n;++i){if(i>=p||i+nxt[i-j]>=p){if(i>=p)p=i;while(p<n&&p-i<m&&s[p]==t[p-i])p++;ext[i]=p-i;j=i;}else ext[i]=nxt[i-j];//cout<<ext[i]<<" ";} } char s[2000001],t[2000001]; int main(){scanf("%s%s",s,t);getext(s,t);int q;scanf("%d",&q);for(int i=1;i<=q;++i){int tmp;scanf("%d",&tmp);printf("%d\n",ext[tmp-1]);} }轉載于:https://www.cnblogs.com/youddjxd/p/10846486.html
總結
以上是生活随笔為你收集整理的KMPEXKMP学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: solaris11 format zpo
- 下一篇: AJPFX关于构造器的总结