KMP演算法C++實現
阿新 • • 發佈:2019-01-06
KMP演算法在資料結構(C語言版)裡算是比較難的地方了,難就難在next陣列的求法,但偏偏很多資料在這一點都比較含糊,下面是我學完KMP的一些思考和程式碼。
一、定位函式(暴力法)
#include<iostream> #include<cstdio> #include<string> using namespace std; int index(string s,string t,int pos){ int i=pos; int j=0; int slen = s.length(); int tlen = t.length(); while(i<slen&&j<tlen){ if(s[i]==t[j]){ i++,j++;} else{ i=i-j+1; j=0; } } if(j==tlen) return i-tlen; return -1; }
二、KMP的模式匹配
講點別的:
實際上KMP就是將模式串向右滑動,如果記錄每個模式串的前後相等的字串,然後下次可以直接往右移到指定的位置繼續匹配,從而減少無意義的匹配。
關鍵就是求next陣列,當P[j]==P[k]時,next[++j]=++k;當P[j]!=P[k]時,等於是自己模式匹配自己,k=next[k]。
ps:記住string物件的length()方法,返回的是一個unsigned int,不能拿它和int 型別的i(j)比較,int型別會被強轉為unsigned int,如果i是-1,那麼在unsigned int中是最大值(因為補碼,int和unsigned int不一樣)
#include<iostream> #include<cstring> #include<string> #include<cstdio> using namespace std; int next[30]; void get_next(string t){ int i=0; next[0]=-1; int k=-1; int tlen = t.length(); while(i<tlen-1){ if(k==-1 || t[i]==t[k]) next[++i]=++k; else k=next[k]; } } int KMP(string s,string t){ int i=0; int j=0; get_next(t); int slen = s.length(); int tlen = t.length(); while(i<slen&&j<tlen){ if(j==-1||s[i]==t[j]){ i++,j++; } else { j=next[j]; } } if(j==tlen) return i-j; else return -1; } int main(){ string s1,s2; cin>>s1>>s2; cout<<KMP(s1,s2)<<endl; }