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;
}

  

posted @ 2013-08-29 15:51  Neptunes  阅读(215)  评论(0编辑  收藏  举报