KMP 算法
KMP 算法包含两个部分:
- 利用 pattern 构建 next 数组
- 利用 next 数据去匹配长字符串
使用 KMP 算法的好处是,对于被匹配的长字符串,我们始终不需要往回走。
next 数组中的每一个元素,比如说 next[i] 代表的是在 pattern 中第 i 个位置之前存在的前缀和后缀相等的长度。比如说 ABCDABCE
它的 next 数组为 -1, 0, 0, 0, 0, 1, 2, 3
。next 数组代表的意义是,匹配失败时,下一次匹配对齐的位置。
vector<int> construct_next(string pattern){
int n = pattern.size();
if (n < 2) return {-1, 0};
vector<int> next(n, 0);
next[0] = -1;
next[1] = 0;
int j = 0, i = 2;
while(i < n){
if (pattern[i - 1] == pattern[j]){
j ++;
next[i] = j;
i ++;
}
else if (j > 0){
j = next[j];
}
else{
next[i] = 0;
i ++;
}
}
return next;
}
vector<int> go(string text, string pattern){
// return start point
vector<int> v;
vector<int> next = construct_next(pattern);
int i = 0, j = 0;
while(true){
if (i == text.size())
break;
if (j == pattern.size()){
v.push_back(i - j);
j = 0;
}
if (text[i] == pattern[j]){
i ++;
j ++;
}
else{
if (j == 0){
i ++;
}
else{
j = next[j];
}
}
}
return v;
}