kmp演算法(字串匹配)
阿新 • • 發佈:2020-09-03
參考視訊:https://www.bilibili.com/video/BV1jb411V78H?from=search&seid=4313084886343126293
參考部落格:https://blog.csdn.net/qq_34181098/article/details/107066929
next陣列(模式串):
1 void buildNext(string& p, int* Next, int n) { 2 int x,y; // x指標指向字首,y指向字尾 3 x = -1; 4 y = 0; 5 while(y < n) { // n 為Next陣列長度6 if(x == -1 || p[x] == p[y]) { 7 Next[++y] = ++x; // x共用 8 } 9 else { 10 x = Next[x]; 11 } 12 } 13 }
kmp:
1 int KMP(string t, string p) { 2 int i = 0; // 主串位置 3 int j = 0; // 模式串位置 4 const int len = p.size() + 1; 5 intnext[len] = { -1 }; 6 buildNext(p,next,p.size()); 7 8 int tsize = t.size(); 9 int psize = p.size(); 10 // while 中的匹配方法是核心,字首表生成和KMP本體匹配都用這個 11 while(i < tsize && j < psize) { 12 if(j == -1 || t[i] == p[j]) { 13 /* 14 j = -1 時(next陣列-1),直接匹配下一個位置。模式串index和next陣列共用15 */ 16 i++; 17 j++; 18 } 19 else { 20 j = next[j]; // 如果匹配不上,則參照next陣列表進行位移 21 } 22 23 } 24 if( j == psize) 25 return i - j; 26 else 27 return -1; 28 }
模板題:https://www.luogu.com.cn/problem/P3375
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 void build_next(char *s, int *next, int len) { 6 int x = -1, y = 0; 7 while(y < len) { 8 if(x == -1 || s[x] == s[y]) 9 next[++y] = ++x; 10 else 11 x = next[x]; 12 } 13 } 14 15 void kmp(char *mstr, char *pstr) { 16 int i = 0, j = 0; 17 int mlen = strlen(mstr), plen = strlen(pstr) + 1; 18 int next[plen] = {-1}; 19 build_next(pstr, next, plen); 20 while(i < mlen) { 21 if(j == -1 || mstr[i] == pstr[j]) { 22 i++; 23 j++; 24 } else { 25 j = next[j]; 26 } 27 //cout << "#" << j << "#" << endl; 28 if(j == plen - 1) { 29 cout << i-j+1 << endl; 30 j = next[j]; 31 } 32 } 33 for(int i = 1; i < plen;i++) { 34 if(i != 1) cout << " "; 35 cout << next[i]; 36 } 37 } 38 39 int main() 40 { 41 char *s1 = new char[1000000], *s2 = new char[1000000]; 42 cin >> s1; cin >> s2; 43 kmp(s1, s2); 44 return 0; 45 }