P3375 【模板】KMP字符串匹配(洛谷)
理解
一.求长度
string类型:
string s;
(1) s.length()
(2)s.size()
char类型:
char s[100];
(1)strlen(s)
(2)sizeof(s) : ‘\0’
二.KMP
模式匹配/字符串匹配
模式串/子串自配 = prefix( & suffix) table
i | 0 1 2 3 4 5 |
---|---|
1/2 | _ a b a b c |
for (int i = 2, j = 0; i <= lp; i++) {//kmp[x] = 0 => j = 0;
while (j && p[i] != p[j + 1]) j = kmp[j];//移动直至匹配
if (p[i] == p[j + 1]) kmp[i] = ++j;
}
模式串&文本串匹配/KMP
i | ___a b a b a b c |
---|---|
j | a b a b c |
for (int i = 1, j = 0; i <= lt; i++) {//kmp[x] = 0 => j = 0;
while (j > 0 && t[i] != p[j + 1]) j = kmp[j];
if (t[i] == p[j + 1]) j++;
if (j == lp) {
cout << i - lp + 1 << endl;
j = kmp[j];
}
}
代码
#include<iostream>
#include<cstring>
#define MAXN 1000005
using namespace std;
char t[MAXN], p[MAXN];
int kmp[MAXN];
int main() {
cin >> t + 1 >> p + 1;
int lt = strlen(t + 1), lp = strlen(p + 1);
for (int i = 2, j = 0; i <= lp; i++) {
while (j && p[i] != p[j + 1]) j = kmp[j];
if (p[i] == p[j + 1]) kmp[i] = ++j;
}
for (int i = 1, j = 0; i <= lt; i++) {
while (j > 0 && t[i] != p[j + 1]) j = kmp[j];
if (t[i] == p[j + 1]) j++;
if (j == lp) {
cout << i - lp + 1 << endl;
j = kmp[j];
}
}
for (int i = 1; i <= lp; i++) cout << kmp[i] << ' ';
return 0;
}