KMP算法
KMP算法是用来匹配字符串的 一个时间复杂度较BF算法 小的算法~
我的注释超详细哦~
#include <stdio.h>
int KMPp(char c);//每次输入后,进行匹配,返回是否匹配成功 成功为1
void nextpp(char *p);//输入子串后 计算KMP++算法的k值
int znum,i,p,n1,n2; //子串长度,循环变量,执行指针,n1n2记录匹配序列位置
char zhch,zch[1000],nextp[1000];//主串临时变量,字串,k值
int main()
{
printf("请输入模式串长度:\n");
scanf("%d",&znum);
if (znum<1000)
{
printf("好的,现在请输入模式串:\n");
scanf("%s",zch);
// for (i=0;i<znum;i++) scanf("%c",&zch[i]);
// printf("不要鸟我 我是测试:%c\n",zch[1]);
nextpp(zch);
printf("好的,现在请输入主串:\n");
p,n1=0;
while(1)
{
scanf("%c",&zhch);
n1++;
if(KMPp(zhch))
{
printf("匹配成功! 从第%d个字符到第%d个字符。",n2-1,n1-1);
break;
}
}
}
else printf("我擦,你也太贪心了、、、");
return 0;
}
int KMPp(char c)
{
if (p==-1) {p=0;return 0;}//比对失败则输入下一个字符
if (p==0) n2=n1;//置序列位置
if (c==zch[p])//如果当前值正确,考虑是否为序列尾
{
if (p!=znum-1) {p++;return 0;}//比对成功 进入下一个字符
else return 1;//匹配成功!
}
else {p=nextp[p];KMPp(zhch);} //不正确则递归
}
void nextpp(char *p) //求最长前缀序列==后缀序列成立的长度 同时 如果zj=zk 则n(j)=n(k) 0
{
//memset(nextp,-1,znum);//清空失败函数
int i,j,x,k,t;
nextp[0]=-1;
nextp[1]=0;
for (i=2;i<znum;i++) //i指构建nextnp[i]
{
for (j=i-1;j>0;j--)//j指前后缀序列的长度 j-1为最大长度
{
k=0;
for (x=0;x<j;x++) if (p[x]!=p[i+x-j]) {k++; break;}
//核心步骤 比对每一个前后缀序列是否相等 求出k 从后比到前 节约步骤
if (k==0) {nextp[i]=j;break;}
}
}
printf("失败函数为:");
for (i=0;i<znum;i++) printf("%d ",nextp[i]);
printf("\n");
}
/*// 我会告诉你们 这下面这个函数是错的- - 每次扫描全部序列 而不是k 以前 但是可以输出正确的结果 原因未明
void nextpp(char *p) //求最长前缀序列==后缀序列成立的长度 同时 如果zj=zk 则n(j)=n(k) 0
{
//memset(nextp,-1,znum);//清空失败函数
int i,j,k,x,t;
nextp[0]=-1;
nextp[1]=-1;
for (i=2;i<znum;i++) //i指构建nextnp[i]
{
for (j=1;j<znum-1;j++)//j指前后缀序列的最大长度
{
for (k=1;k<j;k++)//k指前后缀序列现在检查的长度
{
for (x=0;x<k;x++) {if (p[x]!=p[znum-k+x]) break; }//对于每一长度 分别求0到(k-1)和znum-1到znum-1-k是不是相等
if (x==k-1&&k>t) t=k;//如果全部相等 置s=k,且每次取最大值
}
}
if (p[i]==p[t]) nextp[i]=nextp[t];
else nextp[i]=t;
}
printf("失败函数为:");
for (i=0;i<znum;i++) printf("%d ",nextp[i]);
printf("\n");
}
*/
浙公网安备 33010602011771号