暴力
在S内查找P
如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有:
如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符;
如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0。相当于每次匹配失败时,i 回溯,j 被置为0
KMP 思路
在S内查找P
- 无论S是什么,P字符串都会存在一个next[]数组,记录最大前缀和后缀相等的字符个数
- 然后比较S P时,发现S[7] 和 P[7]不一样, a ≠ c,
- 那么我们让j回退, j = next[j] ,
- 注意 我们比较的是 P[i] 和 S[j+1], 所以 j = = 6 ,也就是 j = next[6[ = 4
- 然后j就在P内回退到位置4 ,指向b
- 然后再让j往后移动,此时j指向P中位置5的元素 a,
- 再和S中的i 比较 c 和 a
注意:
- KMP匹配,是S与P匹配
- next[]数组,求字串P最大前缀和后缀相等的个数
代码
(思路是这样,但是这个题后来数据范围改了,不通过了)
#include <iostream>
using namespace std;
const int M = 1e4 + 10, N = 1e5 + 10;
int m, n;
char p[M], s[N];
int ne[M];
//
int main() {
cin >> m >> p + 1 >> n >> s + 1;
//求ne数组
for(int i = 2, j = 0; i <= m; i++) {
while(j && p[i] != p[j + 1]) j = ne[j];
if(p[i] == p[j + 1]) j++;
ne[i] = j;
}
//kmp匹配
for(int i = 1, j = 0; i <= n; i++) {
while(j && s[i] != p[j + 1]) j = ne[j];
if(s[i] == p[j + 1]) j++;
if(j == m) {
j = ne[j]; //当匹配成功时继续往下匹配
printf("%d ", i - m);
}
}
return 0;
}