在我的初版代码中有这么一句:
while (j && s2[j + 1] != s1[i]) j = kmp[j];
TLE了一个点,感到迷惑,进题解区看到我写的代码思路和第一篇题解几乎一模一样,于是仔细比对后把这行代码改成了:
while (j > 0 && s2[j + 1] != s1[i]) j = kmp[j];
于是过了。
这是初版TLE代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1e6 + 1;
int l1, l2, kmp[maxn], cnt, ans[maxn];
char s1[maxn], s2[maxn];
int main(){
scanf("%s%s", s1 + 1, s2 + 1);
l1 = strlen(s1 + 1);
l2 = strlen(s2 + 1);
int j = 0;
for (int i = 2; i <= l2; i++){
while (j && s2[j + 1] != s2[i]) j = kmp[j];
if (s2[j + 1] == s2[i]) j++;
kmp[i] = j;
}
j = 0;
for (int i = 1; i <= l1; i++){
while (j && s2[j + 1] != s1[i]) j = kmp[j];
if (s2[j + 1] == s1[i]) j++;
if (j == l2){
cnt++;
cout << i - l2 + 1 << endl;
j = kmp[j];
}
}
// cout << endl;
for (int i = 1; i <= l2; i++){
cout << kmp[i] << " ";
}
return 0;
}
这是AC的代码
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1e6 + 1;
int l1, l2, kmp[maxn], cnt, ans[maxn];
char s1[maxn], s2[maxn];
int main(){
scanf("%s%s", s1 + 1, s2 + 1);
l1 = strlen(s1 + 1);
l2 = strlen(s2 + 1);
int j = 0;
for (int i = 2; i <= l2; i++){
while (j && s2[j + 1] != s2[i]) j = kmp[j];
if (s2[j + 1] == s2[i]) j++;
kmp[i] = j;
}
j = 0;
for (int i = 1; i <= l1; i++){
while (j > 0 && s2[j + 1] != s1[i]) j = kmp[j];//唯一改的地方
if (s2[j + 1] == s1[i]) j++;
if (j == l2){
// cnt++;
cout << i - l2 + 1 << endl;
j = kmp[j];
}
}
// cout << endl;
for (int i = 1; i <= l2; i++){
cout << kmp[i] << " ";
}
return 0;
}
理论上这两句话是完全等价的(kmp数组不会出现负数),为什么需要写成这样呢?球大佬解答,感激不尽。