KMP是一个非常实用的字符串匹配算法
推荐网站:
https://www.cnblogs.com/yjiyjige/p/3263858.html https://blog.csdn.net/starstar1992/article/details/54913261/
视频:
KMP字符串匹配算法1—-kmp如何运作
KMP字符串匹配算法2——代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
#include <iostream> #include <cstring> using namespace std;
const int MAXN = 1000000 + 10; typedef int type; type text[MAXN]; type pattern[MAXN]; int prefix[MAXN];
void get_prefix(int len_pattern) { int i = 0, j = -1; prefix[0] = -1; while(i < len_pattern) { if(j == -1 || pattern[i] == pattern[j]) { i++; j++; if(pattern[i] != pattern[j]) prefix[i] = j; else prefix[i] = prefix[j]; } else j = prefix[j]; } }
void kmp(int len_text, int len_pattern) { get_prefix(len_pattern); int i = 0, j = 0; while(i < len_text) { if (j == -1 || text[i] == pattern[j]) { i++; j++; } else j = prefix[j];
if (j == len_pattern) { cout << i - j + 1 << endl; return; } } cout << "-1" << endl; }
int main() { ios::sync_with_stdio(false); int t; cin >> t; while(t--) { int len_text, len_pattern; cin >> len_text >> len_pattern; for(int i = 0; i < len_text; i++) cin >> text[i]; for(int i = 0; i < len_pattern; i++) cin >> pattern[i]; kmp(len_text, len_pattern); } return 0; }
|
1
| 字符编号从1开始,那么if(i%(i-next[i])==0),则i前面的串为一个轮回串,其中轮回子串出现i/(i-next[i])次。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
#include <iostream> #include <cstring> using namespace std;
const int MAXN = 1000000 + 10; typedef char type; type pattern[MAXN]; int prefix[MAXN];
void get_prefix(int len_pattern) { int i = 0, j = -1; prefix[0] = -1; while(i < len_pattern) { if(j == -1 || pattern[i] == pattern[j]) { i++; j++; prefix[i] = j; } else j = prefix[j]; } }
void solve(int len_pattern) { for(int i = 1; i <= len_pattern; i++) { int tmp = i - prefix[i]; if(i % tmp == 0 && i / tmp > 1) cout << i << " " << i / tmp << endl; } cout << endl; } int main() { ios::sync_with_stdio(false); int n, cas = 1; while(cin >> n && n) { cin >> pattern; cout << "Test case #" << cas++ << endl; get_prefix(n);
solve(n); } return 0; }
|