KMP算法的大致思路

作用:处理字符串匹配的问题,比正常遍历要快,时间复杂度为O(n)

KMP的大致思路

在比较俩个字符串时,把一个当做模板串,并求出其next数组,在另一个字符串上进行遍历比较,若不同时可以利用next数组移动模板串,因为不需要每次从头比较模板出所有时间复杂度比直接遍历要快;

前缀表

a a b a a b a a f

a a b a a f

前缀 :{a}, {a,a}, {a,a,b} ,{a,a,b,a} , {a,a,b,a,a } 即不包含尾部的所有子串 {a,a,b,a,a,f} 不是因为他包含了尾部

后缀:{f}, {a,f}, {a,a,f}, {b,a,a,f}, {a,b,a,a,f}

即不包含头部的所有子串 {a,a,b,a,a,f} 不是因为他包含了头部

核心:求最长前后缀,

a 0;

aa 1;

aab 0;

aaba 1;

aabaa 2;

aabaaf 0;

得到序列 0 1 0 1 2 0;这个就是前缀表

匹配过程

a a b a a b a a f

a a b a a f

0 1 0 1 2 0

在遍历到b即f对应位置时发现不一致,在此时求前一位的最长相等前后缀 在此样例为2 ,此时移动子串下标为2的元素到f位置(这个2为前面的前一位的最长相等前后缀)

next 数组(遇到冲突时由next数组判断移动位置)

next数组核心为前缀表,不同的数组可能会对前缀表进行不同操作,如整体后移或者整体减一,目的为了进一步优化时间复杂度

代码实现

void get_next(char *a,int*next)//a表示模板串,next表示要求的数组
{
    int i=1,j=0;//j指向前缀末尾位置,i指向后缀末尾位置
    //为比较前缀与后缀是否相等,所以i!=j
    next[0]=0;
    int n=0;//n表示a的长度
    for(int i=0;;i++)
    {
        if(a[i]=='\0')
            break;
        else
            n++;
    }
    for(int i=1;i<n;i++)
    {
        while(a[i]!=a[j]&&j>0)//前后缀不相同
        {
            j=next[j-1]; 
		}
        if(a[i]==a[j])//前后缀相同
        {
            j++;//前缀继续向后走
            next[i]=j;//填充数组
        }
    }
}
int KMP(char *a,char *b,int x)
{
    int i=0;//i指向a,j指向b,俩个指针
    int j=0;
    int next[100];
    get_next(a,next);
    int a.length=0,b.length=0;
    for(int i=0;;i++)//得到a的长度
    {
        if(a[i]=='\0')
          break;
        else
            a.length++;
	}
     for(int i=0;;i++)//得到b的长度
    {
        if(a[i]=='\0')
           break;
         else 
             b.length++;
	}
    while(i<a.length&&j<b.length)
    {
		if(i=0||a[i]==b[j])
        {
            i++;
            j++;
		}
        else
        {
            j=next[j-1];
		}
	}
    if(j>b.length)
        return i-a.length;
    else
        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值