求助kmp模板中的一个小细节
查看原帖
求助kmp模板中的一个小细节
347839
Daniel_7216楼主2024/9/7 21:57

在我的初版代码中有这么一句:

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数组不会出现负数),为什么需要写成这样呢?球大佬解答,感激不尽。

2024/9/7 21:57
加载中...