C语言KMP字符串匹配算法

来源:互联网 发布:gta5ol女角色捏脸数据 编辑:程序博客网 时间:2024/05/21 00:18


KMP算法模版

Kmp算法是用于求一长字符串和短字符串按一定规律匹配的情况,可以求是否能在长串中找到短串

         其思想就是通过一个next数组对短串进行处理,找到短串前后某两个位置是否具有相同的前后缀,用next[i]表示最后以b[i]结尾的前缀和后缀与模式串前缀的最长匹配数。

这样两字符串在匹配是,若在长串与短串某位置发现两字符不同,不能继续匹配时,短串下标i不一定要回到短串的首字符继续匹配,短串可以跳到next[i]的位置。从而降低算法的时间复杂度,从原来的O(n*m)降低到O(n+m)。//n,m表示两串长度

代码如下:

#include<cstdio>#include<cstring>const int Max=10010;char str[Max],str1[Max];//这里匹配的的浪字符串,Kmp算法也可用于两个数组等。int nextt[Max];void Next(int len){    int i=-1,j=0;//将i初始化为-1,是为了维护两个指针i,j,便于对next数组进行初始化,保证i在j前    nextt[0]=-1; //将短串首字符的next值赋值为-1,便于后面Kmp()函数循环中i跳到到短串首时做特殊处理    while(j<len)    {        if(i==-1||str[i]==str[j])//i==-1时,也需要将i,j进行自增,才能保证i在j之前,此时i==0,j==1.并把next[1]=0,        {                        //即短串第二个字符b[1]的前缀下标为0.在j循环过程中,i做相应的变化。若发现j位置与i位置            ++i,++j;             //存在相同的前缀,则用nextt[j]=i记录下来,用于Kmp()函数中匹配时运用            nextt[j]=i;        }        else            i=nextt[i];      //若短串中i位置和j位置字符不同,i跳到next[i]位置  原因:当短串中i位置和j位置字符不等时,说明    }                        //此时i位置和j位置没有相同的前缀,但可能在i位置以前找到与j+1位置相同的前缀    for(int i=0; i<=len; i++)                 //输出next数组的值        printf("%d%c",nextt[i],i==len?'\n':' ');    return ;}int Kmp(int len,int len1){    int i=0,j=0;    while(j<len1)//以长串长度做循环的终止条件    {        if(i==-1||str[i]==str1[j])        {            ++i,++j;        }        else            i=nextt[i];        if(i==len)  //当i==len时,说明短串已到达结尾b[len-1],在if中自增以后其值与len相同            return 1;  //此时表明在长串中找到了符合条件的短串,程序返回1.若程序到循环终止在长串中也没有    }                  //找到符合条件的短串,返回0    return 0;}int main(){    int n;    scanf("%d",&n);    while(n--)    {        scanf("%s %s",str,str1);//str为短串,str1为长串        int len=strlen(str);        int len1=strlen(str1);        Next(len);        if(Kmp(len,len1))//len为短串长度,len1为长串长度,以这两个长度做Kmp()函数循环的终止条件            printf("Yes\n");  //函数也可能在没到终止条件是结束,此时匹配已经完成!即在Kmp()函数        else                  //结束条件之前在长串中已经找到了符合条件的短串            printf("No\n");        if(nextt[len]&&len%(len-nextt[len])==0)//求循环节(最长前后缀循环次数),len为短串长度,next[len]表示最后b[len-1]结尾的前缀和后缀        {                                      //与模式串前缀的最长匹配数。则len-next[len]为循环节长度,len/(len-nextt[len])即为循环节            printf("%d\n",len/(len-nextt[len]));        }        else            printf("Can't\n");    }    return 0;}
希望对大家有所帮助。


3 0
原创粉丝点击