KMP算法(未优化版本,算法导论原版)

kmp是经典的单模式串字符串匹配算法,对于一个字符串在长文本中的匹配很有效。
kmp算法包括两部分,对模式串的预处理和模式串匹配**

1、模式串预处理
这一部分关键在于next数组的构造,相当于对模式串进行kmp匹配。注意,字符串数组与next数组的首字符不存储信息。
next数组中储存当该字符的下一个不匹配时,下一步应当跳转到哪里,即,到此为止该字符串的最长公共前缀,后缀的长度。
详细见代码注释
预处理代码的解释图

void next(int *next, char *c)//字符串从c[1]开始赋值
{
    //k为要比较的字符的前一个的下标,一开始比较c[1]c[2],所以k初始化为0
    int k = 0;
    //首字符的next值初始化为0,说明包①含这个字符的字符串前后缀长为0,②即要比较的字符c[1]的前一个
    next[1] = 0;//注意next数组值的两层含义
    //一开始比较c[1]c[2],i初始化为2,
    for (int i = 2; i < strlen(c); i++)//next数组最后一个的值比strlen值小一,所以不要取等
    {
        //当k可以回溯且不匹配时,让k回溯
        //k初始化为0,保证可回溯,即k>0
        while (k > 0 && c[i] != c[k + 1])
        {
            k = next[k];//对前串来说a[k]是a1中前缀的最后一个字符所在位置
        }
        if (c[i] == c[k + 1])//若匹配则k+1,
            k++;
        next[i] = k;//包含i的字符串的前缀长=加过1的k。
    }
}

2、kmp匹配部分
原理与模式串匹配相似,只不过是两个字符串的匹配

void kmp(char *t, char *p)//t为长串,p为短串
{
    int *next;
    next = (int *)malloc(sizeof(int)*(strlen(p)+1));
    buildnext(next, p);
    int k = 0;//k为要比较的字符的前一个的下标,一开始比较模式串中的c[1],k初始化为0
    for (int i = 1; i < strlen(t); i++)//长串的最后一个字符的下标为长度-1
    {
        while (k>1 && p[k + 1] != t[i])
            k = next[k];
        if (p[k + 1] == t[i])
            k++;
        if (k == strlen(p)-1)
        {
            printf("开始下标为%d\n", i - strlen(p)+1+1);
            k = next[k];//寻找下一个匹配串
        }
    }

这种原始的kmp算法有一个弊端,当字符串重复性很高时(例如ababababag),它的效率和朴素匹配没啥区别了。因为当重复性很高时,如果有一位失配,那么再向后移动仍然失配。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值