题意不解释了。
第一版本代码:WA
#include <iostream>
#include <cstring>
using namespace std;
char s1[1000000+10], s2[10000+10];
void get_nextval(char* T, int nextval[])
{
int i = 1, j = 0;
nextval[1] = 0;
while(i < T[0])
if(j == 0 || T[i] == T[j]) {
++i;
++j;
if(T[i] != T[j])
nextval[i] = j;
else
nextval[i] = nextval[j];
} else
j = nextval[j];
}
int Index_KMP(char* S, char* T, int pos, int next[])
{
int i = pos, j = 1;
while(i <= S[0] && j <= T[0])
if(j == 0 || S[i] == T[j]) {
++i;
++j;
} else
j = next[j];
if(j > T[0])
return i - T[0];
else
return 0;
}
int main()
{
int t;
cin >> t;
getchar();
while(t--) {
int n, m, i;
memset(s1, 0, sizeof(s1));
memset(s2, 0, sizeof(s2));
gets(s2+1);
gets(s1+1);
n = strlen(s1+1);
m = strlen(s2+1);
s1[0] = n;
s2[0] = m;
int *next = new int[m+1];
get_nextval(s2, next);
int pos = 1;
int cnt = 0;
while(pos <= n - m +1) {
if((pos =Index_KMP(s1, s2, pos, next)) != 0) {
cnt++;
pos = pos + 1;
}
else
break;
}
cout << cnt << endl;
delete[] next;
}
return 0;
}
没发现哪里明显的错误。网上参考了一下代码。模仿在kmp里面进行统计。在最后一个匹配的时候进行下标转化
这个由于下标的不同会导致,next[len2+1]无定义。程序出错。代码优化后也会使得减少了匹配数目。
一个解决方法是,不使用改进后的kmp算法。而采用原始kmp算法计算next数组。
虽然在本机上测试通过,这时候的代码还是wa。怀疑数据的问题。后来调试的时候发现S[0],T[0]是char的类型。而char的存储范围明显不足。改用int存储后,顺利AC
AC代码:
#include <iostream>
#include <cstring>
using namespace std;
char s1[1000000+10], s2[10000+10];
int len1, len2;
void get_nextvalval(char* T, int nextvalval[])
{
int i = 1, j = 0;
nextvalval[1] = 0;
while(i < len2) {
if(j == 0 || T[i] == T[j]) { //使用原始的kmp计算next数组
++i;
++j;
//if(T[i] != T[j])
nextvalval[i] = j;
//else
// nextvalval[i] = nextvalval[j];
}
else j = nextvalval[j];
}
}
int Index_KMP(char* S, char* T, int pos, int nextval[])
{
int i = pos, j = 1;
int cnt = 0;
while(i <= len1 && j <= len2) {
if(j == 0 || S[i] == T[j]) {
if(j >= len2) {
cnt++;
//printf("%d\n", i);
j = nextval[j];
} else {
++i;
++j;
}
}
else j = nextval[j];
}
return cnt;
}
int main()
{
int t;
cin >> t;
getchar();
while(t--) {
memset(s1, 0, sizeof(s1));
memset(s2, 0, sizeof(s2));
gets(s2+1);
gets(s1+1);
len1 = strlen(s1+1);
len2 = strlen(s2+1);
int *nextval = new int[len2+1];
get_nextvalval(s2, nextval);
int cnt = 0;
cnt = Index_KMP(s1, s2, 1, nextval);
cout << cnt << endl;
delete[] nextval;
}
return 0;
}
如果使用改进kmp,则需要对源代码进行略微的修改。
#include <iostream>
#include <cstring>
using namespace std;
char s1[1000000+10], s2[10000+10];
int len1, len2;
void get_nextvalval(char* T, int nextvalval[])
{
int i = 1, j = 0;
nextvalval[1] = 0;
while(i <= len2) { //改。注意这里的等号
if(j == 0 || T[i] == T[j]) { //使用原始的kmp计算next数组
++i;
++j;
if(T[i] != T[j])
nextvalval[i] = j;
else
nextvalval[i] = nextvalval[j];
}
else j = nextvalval[j];
}
}
int Index_KMP(char* S, char* T, int pos, int nextval[])
{
int i = pos, j = 1;
int cnt = 0;
while(i <= len1 && j <= len2) {
if(j == 0 || S[i] == T[j]) {
i++;
j++;
if(j > len2) {
cnt++;
//printf("%d\n", i);
j = nextval[j];
}
}
else j = nextval[j];
}
return cnt;
}
int main()
{
freopen("1686.txt", "r", stdin);
int t;
cin >> t;
getchar();
while(t--) {
memset(s1, 0, sizeof(s1));
memset(s2, 0, sizeof(s2));
gets(s2+1);
gets(s1+1);
len1 = strlen(s1+1);
len2 = strlen(s2+1);
int *nextval = new int[len2+10];
get_nextvalval(s2, nextval);
int cnt = 0;
cnt = Index_KMP(s1, s2, 1, nextval);
cout << cnt << endl;
delete[] nextval;
}
return 0;
}