下标均从1开始。
字符串 \(s\) 的前缀函数 \(\pi[i]\) 表示长度为 \(i\) 的前缀中最长的 border 的长度。
kmp 找出模式字符串 \(t\) 在文本字符串 \(s\) 中出现的所有的位置。
namespace KnuthMorrisPratt {
vi getPi(char *s) {
int slen = strlen(s + 1);
vi pi(slen + 1);
for(int i = 2, j = 0; i <= slen; ++i) {
for(; j && s[i] != s[j + 1]; j = pi[j]);
j += (s[i] == s[j + 1]);
pi[i] = j;
}
return pi;
}
vi kmp(char *s, char *t) {
int slen = strlen(s + 1), tlen = strlen(t + 1);
vi pi = getPi(t), res;
for(int i = 1, j = 0; i <= slen; ++i) {
for(; j && s[i] != t[j + 1]; j = pi[j]);
j += (s[i] == t[j + 1]);
if(j == tlen)
res.pb(i - tlen + 1);
}
return res;
}
}
原文:https://www.cnblogs.com/purinliang/p/14067447.html