1. 程式人生 > 實用技巧 >kmp演算法(字串匹配)

kmp演算法(字串匹配)

參考視訊: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     int
next[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 }