kmp算法(字符串匹配)

来源:互联网 发布:java测试工程师面试题 编辑:程序博客网 时间:2024/04/25 07:56

(1)kmp算法的用途:

KMP算法是用来处理字符串匹配的。换句话说,给你两个字符串,你需要回答,B串是否是A串的子串(A串是否包含B串)。例如”Today is Tuesday”.中是否包含”day”,在哪些位置包含。

(2)kmp算法的概述:

假如,A="abababaababacb",B="ababacb",我们来看看KMP是怎么工作的。我们用两个指针i和j分别表示,A[i-j+ 1..i]与B[1..j]完全相等。

也就是说,i是不断增加的,随着i的增加j相应地变化,且j满足以A[i]结尾的长度为j的字符串正好匹配B串的前 j个字符(j当然越大越好),现在需要检验A[i+1]和B[j+1]的关系。当A[i+1]=B[j+1]时,i和j各加一;什么时候j=m (B串的长度)了,我们就说B是A的子串(B串已经整完了),并且可以根据这时的i值算出匹配的位置。(如果初始i=0,j=0;那么匹配位置是i-m+1)。当A[i+1]<>B[j+1],KMP的策略是调整j的位置(减小j值)使得A[i-j+1..i]与B[1..j]保持匹配且新的B[j+1]恰好与A[i+1]匹配(从而使得i和j能继续增加)。我们看一看当 i=j=5时的情况。位置。从上面的这个例子,我们可以看到,新的j可以取多少与i无关,只与B串有关。我们完全可以预处理出这样一个数组P[j],表示当匹配到B数组的第j个字母而第j+1个字母不能匹配了时,新的j最大是多少。P[j]应该是所有满足B[1..P[j]]=B[j-P[j]+1..j]的最大值。

i: 1 2 3 4 5 6 7 8

(3)kmp算法模板:

首先,定义两个字符数组 str1[M] (母串),str2[N] (子串 )(N<M)定义数组p[N];

kmp 算法所需要的函数:

void getp ( )       //对子串进行预处理

{

          int i = 0, j = -1;

          p[i] = j;

          while( i < len2 )             //子串的长度为len2

          {

                  if( j == -1 || str2[i] == str2[j] )

                  {

                               i++, j++;

                               p[i] = j;

                              }

                   else

                       j = p[j]; 

}

void kmp( )

{
                int i = 0,j = 0;

                getp( );

                while( i < len1 )

               {

                        if( j == -1|| str1[i] == str2[j] )

                       {

                                   i++,j++;

                                  if( j == len2 )

                                        cnt++;         //j ==len2 时,匹配成功,cnt 记录有多少次匹配(初始:cnt = 0)

                              }

                        else

                            j = p[j];

}

(4) getp函数的几个性质:

设 有一字符串 str[N]经过 getp函数处理。

定义p数组;

(1)  若 len %( len - p[len]) == 0,那么这个字符串就是一个周期串,例如 abcabcabc;

 ( 2 )    若(1)成立,那么有 周期串的循环节的长度为 len - p[len];周期串的循环节的循环次数为 len / ( len - p[len]);


(5) p数组的求法:

例如: 模式串 a b a a b c a c 
            next值  0 1 1 2 2 3 1 2

1、next数组的求解方法是:第一位的next值为0,第二位的next值为1,后面求解每一位的next值时,根据前一位进行比较。首先将前一位与其next值对应的内容进行比较,如果相等,则该位的next值就是前一位的next值加上1;如果不等,向前继续寻找next值对应的内容来与前一位进行比较,直到找到某个位上内容的next值对应的内容与前一位相等为止,则这个位对应的值加上1即为需求的next值;如果找到第一位都没有找到与前一位相等的内容,那么需求的位上的next值即为1。(即第一位的值0 加上 1等于该位的值)

2、前两位必定为0和1。
计算第三位的时候,看第二位b的next值,为1,则把b和1对应的a进行比较,不同,则第三位a的next的值为1,因为一直比到最前一位,都没有发生比较相同的现象。

3、计算第四位的时候,看第三位a的next值,为1,则把a和1对应的a进行比较,相同,则第四位a的next的值为第三位a的next值加上1。为2。因为是在第三位实现了其next值对应的值与第三位的值相同。

4、计算第五位的时候,看第四位a的next值,为2,则把a和2对应的b进行比较,不同,则再将b对应的next值1对应的a与第四位的a进行比较,相同,则第五位的next值为第二位b的next值加上1,为2。因为是在第二位实现了其next值对应的值与第四位的值相同。

5、计算第六位的时候,看第五位b的next值,为2,则把b和2对应的b进行比较,相同,则第六位c的next值为第五位b的next值加上1,为3,因为是在第五位实现了其next值对应的值与第五位相同。

6、计算第七位的时候,看第六位c的next值,为3,则把c和3对应的a进行比较,不同,则再把第3位a的next值1对应的a与第六位c比较,仍然不同,则第七位的next值为1。
7、计算第八位的时候,看第七位a的next值,为1,则把a和1对应的a进行比较,相同,则第八位c的next值为第七位a的next值加上1,为2,因为是在第七位和实现了其next值对应的值与第七位相同。










0 0
原创粉丝点击