zoukankan      html  css  js  c++  java
  • KMP(思路分析)

    *介绍:

          KMP算法是在给定的一串字符串中查找是否有目标串。
    *分析:
    1、一般解法
          对于以上问题,假如用朴素算法,我们容易想到:用目标串(长度为n)的第1个字符依次与给定串(长度为m)的第1个至最后一个字符对齐匹配,直到找到目标串为止。这样算法复杂度是m*n。
    2、KMP算法:
    思路分析:
          KMP算法通过建立一个数组(一般命名为next)来记录目标串的自身特征从而简化匹配过程,令算法的复杂度降至m+n。
          举例,假设目标串为:  a b c a b c d d e a
          对应next数组的值为: 0 0 0 1 2 3 0 0 0 1
          通过观察我们会发现next数组记录的是以当前字符为后缀,以第一个字符为前缀的相同字符串(这样的字符串可能有很多个)其中最长的一个的长度。例如:对于例子中的第一个b,以他为后缀,我们可以找到2个字符串(ab,b) 以第一个字符a为前缀的字符串也有3个(a,ab),由于从第1个字符到当前字符不再计算范围之内所以最长长度为0;我们再看第2个b,以他为后缀的字符串有(abcab,bcab,cab,ab,b),以第1个字符a为前缀的字符串有(a,ab,abc,abca,abcab)其中相同且最长的是ab这个字符串所以next数组的值为2。
           知道next数组是怎样得出的之后我们进一步发现可以这样理解:next数组记录的是与当前字符地位相当的字符的位置。例如,字符串中的第2个b对应的next数组值为2,我们由此考察字符串中第2个字符恰好也是b,而且从第1个字符开始到我们找到的b为止的字符串,与刚开始的b前面相应长度的字符串完全一样(都是ab),同样我们可以考察其他字符,next数组中的0则代表找不到一个相当的字符。
           分析到这里我们自然想到:在字符串的匹配过程中我们假如刚开始匹配的很好,而下一个字符就不匹配了,我们就可以通过next数组找到一个字符串来代替当前串继续匹配,而不用像朴素算法那样回到开始。这正是KMP算法省时间的原因。
     
    关于next数组的获取:
            我们得到next数组取值的过程呢其实是在令next数组内部与自身匹配,所以思路和以上极为相似。next数组需要借助前面的取值来确定后一个数的取值。假如当前字符(第2个b)和其前面的字符(第2个a)的next数组指向的字符(第1个a)的后一个字符(第1个b)相同,那么当前字符的next数组值就是前一个字符next数组值加1;假如不相同(例如第1个d),我们就需要以同样的思路考察与当前字符前面的字符(第2个c)地位相当的字符(即next数组指向的字符——第1个c),我们发现依然不相同并且此时已经没有与第1个c地位相当的字符,所以next数组的值只能是0。整个过程我们仍是在利用地位相当的字符,所以next数组获取的代码与KMP算法的主代码非常像。
    *代码:
    #include<iostream>
    #include<cstring>
    using namespace std;
    int next[1000],lent,lenp;
    char text[1000],part[1000];
    void get_next()//获取next数组
    {
        next[0]=-1;
        int i=0,j=-1;
        while(i<lenp)
        {
            if(part[i]==part[j]||j==-1)
            {
                i++;
                j++;
                next[i]=j;
            }
            else
                j=next[j];
        }
    }
    int KMP()//主代码
    {
        int i=0,j=0;
        get_next();
        while(i<lent&&j<lenp)
        {
            if(j==-1||text[i]==part[j])
            {
                i++;
                j++;
            }
            else
                j=next[j];
        }
        if(j>=lenp)return i-lenp;
        else
            return -1;
    }
    
    int main()
    {
       cin>>text>>part;
       lenp=strlen(part);
       lent=strlen(text);
       cout<<KMP();//此处是输出匹配开始的数组下标
       return 0;
    }
    

      

  • 相关阅读:
    python-包和模块
    电荷量 电流 电压 功率
    h264 aac 封装 flv
    flv 解封装
    flv格式详解+实例剖析
    rtmp直播推流(一)--flv格式解析与封装
    nginx statistics in multi-workers
    windows平台最简单的rtmp/hls流媒体服务器
    Node-Media-Server
    ffmpeg 基本数据结构和对象: AVPacket、AVPicture、AVFrame
  • 原文地址:https://www.cnblogs.com/Neptunes/p/3289312.html
Copyright © 2011-2022 走看看