题目链接:传送门
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int next1[1000];
int ans;
void cal_next(char ptr[])
{
int len=strlen(ptr);
int k=-1;
next1[0]=-1;
for (int q = 1; q < len; q++)
{
while (k > -1 && ptr[k + 1] != ptr[q])//如果下一个不同,那么k就变成next[k],注意next[k]是小于k的,无论k取任何值。
{
k = next1[k];//往前回溯
}
if (ptr[k + 1] == ptr[q])//如果相同,k++
{
k = k + 1;
}
next1[q] = k;//这个是把算的k的值(就是相同的最大前缀和最大后缀长)赋给next[q]
}
}
void KMP(char str[],char ptr[])
{
cal_next(ptr);
int len1=strlen(str);
int len2=strlen(ptr);
int j=0;//用于ptr数组
for(int i=0;i<len1;i++)
{
while(j>0 && str[i] != ptr[j])
j=next1[j];
if(str[i] == ptr[j])
j++;
if(j==len2)
{
ans++;
j=0;
}
}
}
int main()
{
char str[100];
char ptr[100];
while(scanf("%s",str) && str[0]!='#')
{
ans=0;
cin>>ptr;
KMP(str, ptr);
cout<<ans<<endl;
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int next1[1000];//这里数组在定义时,若直接用next[],老是出现编译错误
//next[i]表示 前i-1个字符 相同的最长前缀和最长后缀的长度 //-1表示不存在,0表示长度为1,1表示长度为2
int ans;
void cal_next(char ptr[])
{
int len=strlen(ptr);
int k=-1;//记录最大next?//最长前缀和最长后缀的长度
next1[0]=-1;
/*
若用这段代码,虽然能解题,但测试next1数组时,会发现有bug 错
这段待更正
int i=0;
while(i<len)
{
if(k==-1 || ptr[i]==ptr[k])
{
i++;
k++;
next[i]=k;
}
else
k=next[k];//递归,在最长前后缀中间寻找?
}*/
for (int q = 1; q < len; q++)
{
while (k > -1 && ptr[k + 1] != ptr[q])//如果下一个不同,那么k就变成next[k],注意next[k]是小于k的,无论k取任何值。
{
k = next1[k];//往前回溯
}
if (ptr[k + 1] == ptr[q])//如果相同,k++
{
k = k + 1;
}
next1[q] = k;//这个是把算的k的值(就是相同的最大前缀和最大后缀长)赋给next[q]
}
/*for(int i=0;i<len;i++)
cout<<next[i]<<" ";
cout<<endl;*/
}
void KMP(char str[],char ptr[])
{
cal_next(ptr);
int len1=strlen(str);
int len2=strlen(ptr);
//int i=0;//用于str数组
int j=0;//用于ptr数组
//while(i<len1)
for(int i=0;i<len1;i++)
{
while(j>0 && str[i] != ptr[j])
j=next1[j];
if(str[i] == ptr[j])
j++;
if(j==len2)
{
ans++;
j=0;
}
// i++;
}
}
int main()
{
char str[100];
char ptr[100];
while(scanf("%s",str) && str[0]!='#')
{
ans=0;
cin>>ptr;
KMP(str, ptr);
cout<<ans<<endl;
}
return 0;
}