KMP实现

//KMP算法在我看来关键在于求next数组以及利用next数组来做匹配;
//或者说怎么样才能让匹配串能够跳跃的匹配进而减少时间,这就需要用到Next数组;
//还要知道next数组存储的是什么?next数组存储的是 匹配串的下标:理解一下就是在不匹配的时候:: j=next[i],,
//next数组的含义代表当前字符之前的字符串的最大公共前后缀;
//当不匹配时j的next值会告诉你下一步j会在哪个位置;
//想等的时候两个串的指针同时向下移动
//*但是如果不相等就需要用到next数组*//
//首先我们应该知道的是在匹配串p中的每一个位置都有可能与原串不匹配。


//那么如何来寻找这个next数组呢?一般是后面的next值是根据前面的next值求出来的;
//我们还可以知道,next数组的第一个和第二个一定是 -1  和  0;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
    int i=0,j=0,k=-1;
    int m=0;
    int next[999]={0};
    int cun[999];
    int sum=0,sum1=0;
    char t[999]={'a','b','a','b','s','d','a','b','a','b','h','i'};
    char p[123]={'a','b','a','b'};
    next[0]=-1;

//  这串求模式串的长度;
    while(1)
    {
        if(p[m]>='a'&&p[m]<='z')
        {
            sum++;
            m++;
        }
        else
            break;

    }
    printf("匹配串长度:%d\n",sum);


//  这组代码求得是 文本串的长度
    m=0;
    while(1)
    {
        if(t[m]>='a'&&t[m]<='z')
        {
            sum1++;
            m++;
        }
        else
            break;

    }
    printf("%文本串长度:d\n",sum1);


//  j循环只需要到倒数第二个就可以了,因为第 j+1 个 next数组的值是由 第 j  个数组的值求出来的;
//  而且我们知道next数组的第一个和第二个的值是固定的;

     while(j<sum-1)
    {
        if(k==-1||p[j]==p[k]){
            j++;
            k++;
            next[j]=k;
        }
        else{
            k=next[k];
        }
    }
    printf("next数组:");
    for(i=0;i<=sum-1;i++)
        printf("%d ",next[i]);
    printf("\n");


//  下面来利用 next 数组,这里和BF算法差不多,相同就全下移,
//不同就采用next数组,这也是next数组被发明的原因
    i=0,j=0;
    m=0;
//当模式串和文本串的第一个的字符不一样那么就会执行 else ,将 j=-1;
//然后,进入if语句 将 i加1,j加1。此时的情况是 查看 模式串的第一个和文本串的第二个是否匹配
// 。。。如果还是不匹配 那么 j 还将变成-1 ,会再次进入 if语句 使 j加1,i加1;
// 。。。再次检查模式串的第一个和文本串的第三个是否匹配;
//如此周而复始,直到找到文本串中一个字符与模式串第一个字符相同
//  //原来的一种写法使当 指针到达 各个串的末尾的时候 会  推出循环 :
// 退出循环我认为只有两种情况  :第一种就是 模式串指针到达最后并且越界这说明找到一个匹配的地方
//  第二种情况就是 文本串到达最后没找到一个字符与模式串的字符相同(此时文本串的指针会一直向后移动知道文本串越界)
// 还有就是 文本串指针正常移动::也会造成文本串数组越界。


//假设:我们知道 可以匹配但是不知道有几处。这样的话,一定会推出循环然后输出  匹配的位置;
//但是 现在我想 如果 文本串中有若干处 能够匹配的地方 我想将他们的位置都找出来,该怎么办呢???
    while(i<sum1)
    {
    if(j==sum)
        {
            cun[m]=i-j;
            m++;
            i++;
            j=0;

        }
        if(j==-1||t[i]==p[j])
        {
            i++;
            j++;
        }
        else
        {
                j=next[j];
        }
    }
    for(i=0;i<m;i++)
        printf("%d ",cun[i]);
    return 0;
}


 

 

 

 

 

 

最后附上两个大佬的博文 ,我向他们和其他的老师学习,为了帮助其他人,附上两位老师的代码,并再次致以崇高的敬意,如果有什么不当之处或有侵权现象,请与我联系。

 

https://blog.csdn.net/v_july_v/article/details/7041827#

 

https://www.cnblogs.com/yjiyjige/p/3263858.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值