以下是我自己写的关于KMP的一个模版题,这能有助于理解吧,这里用了next数组的升级版,不是原封的next数组;原封next数组我会贴在更下面:(代码我也写有注释)
#include <bits/stdc++.h>
using namespace std;
void get_nextval();
int KMP(int pos);
int nextval[255];
char T[10],S[100];
int main()
{
int pos,ans;
printf("请输入S:\n");
scanf("%s",&S[1]);
getchar();
printf("请输入T:\n");
scanf("%s",&T[1]);
T[0]=strlen(T);
S[0]=strlen(S);
printf("请输入pos:\n");
scanf("%d",&pos);
ans=KMP(pos);
printf("%d\n",ans);
return 0;
}
void get_nextval()// 找next数组
{
int i=1,j=0;
nextval[1]=0;//第一个都是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];//这里就是前缀后缀不相同,直接赋值回溯;
//printf("333 %d\n",nextval[i]);这个输出是来测试里面每一个next的值得;
}
}
int KMP(int pos)//这里的pos是从主函数传过来的,表示主函数要求从pos之后开始匹配;
{
int i=pos;//这个pos可以要也可以不要;
int j=1;
get_nextval();
while(i<=S[0]&&j<=T[0])//求得next数组后再来匹配T;
{
if(j==0 ||S[i]==T[i])
{
i++;j++;
}
else//匹配不成功就把j变化,j必须得回到前面去;
{
j=nextval[j];
}
}
if(j>T[10])
return i-T[0];//返回匹配成功的位置
else
return 0;
}
原封next数组就是下面的代码,其他部分相同,就是求next数组那里改了而已,这里就和很多书上说的一样了。不过建议用上面一种;
只看next数组那一部分:
#include <bits/stdc++.h>
using namespace std;
void get_nextval();
int KMP(int pos);
int nextval[255];
char T[10],S[100];
int main()
{
int pos,ans;
printf("请输入S:\n");
scanf("%s",&S[1]);
getchar();
printf("请输入T:\n");
scanf("%s",&T[1]);
T[0]=strlen(T);
S[0]=strlen(S);
printf("请输入pos:\n");
scanf("%d",&pos);
ans=KMP(pos);
printf("%d\n",ans);
return 0;
}
void get_nextval()
{
int i=1,j=0;
nextval[1]=0;//第一个都是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];//这里就是前缀后缀不相同,直接赋值回溯;
printf("333 %d\n",nextval[i]);
}
}
int KMP(int pos)//这里的pos是从主函数传过来的,表示主函数要求从pos之后开始匹配;
{
int i=pos;
int j=1;
get_nextval();
while(i<=S[0]&&j<=T[0])//求得next数组后再来匹配T;
{
if(j==0 ||S[i]==T[i])
{
i++;j++;
}
else//匹配不成功就把j变化;
{
j=nextval[j];
}
}
if(j>T[10])
return i-T[0];//返回匹配成功的位置
else
return 0;
}