《数据结构和算法》之KMP算法

    xiaoxiao2021-03-25  71

    一,KMP算法

           KMP算法,全称就是克努特-莫里斯-普拉特算法,是为了避免大量的重复遍历的情况。举个例子:

                                       

                                                                                                            图 1 遍历对比匹配图1

                                        

                                                                                                            图2 遍历对比匹配图2

              从图1和图2中可以看出来,在图1中如果依次匹配,到5的时候匹配不成功,此时要回头重新匹配,从i=2,j=1的位置开始匹配,这就是回溯法的思想,就这样依次来回地回溯对比验证,最后才给出一个结论是否匹配成功。

                                       

                                                                                                                   图 3  思路启发一

           思路启发一,在图3中可以看到在上面的匹配中,当i=j=5的时候,是S[5]与T[5]不相等,即不匹配,此时要重新进行匹配,分析可知S[1]=T[1],S[2]=T[2],S[3]=T[3],S[4]=T[4],而T[1]不等于T[2],T[1]不等于T[3],T[1]不等于T[4],T[2]也不等于T[3],T[2]也不等于T[4],此时就不用将T[1]与S[1]\S[2]\S[3]\S[4]相匹配,直接让T[1]与S[5]进行匹配,即如图3下面的演示那样。这个时候提高了效率。

                                       

                                                                                                         图4  思路启发二

             这个思路启发二看上去肯定不符合启发一的情况,此时T[1]与S[2]是相等的,T[1]=T[2],这个时候可以直接认为T[1]=S[2],匹配下一个,即匹配T[2]与S[3],依次匹配下去就会出现匹配成功的结果。

                                      

                                                                                                            图 5   思路启发三   

            在图5中可以看到,T[1]=T[2]=S[4]=S[5],此时可以直接从T[3]开始匹配,这样就提高了效率。

                                       

                                                                                                          图6  思路启发四

              在图6思路启发四中可以看到,根据前面的一二三的经验这个时候可以很明显从T[4]开始匹配。这样得出的一些规律就是KMP算法。问题是由模式串决定的,而不是目标串决定的。主要是为了保证 i 不再回溯。避免了效率低下的问题。

    二,KMP算法的实现

           1,首先get_next函数的编写

                       

    #include <stdio.h> typedef char* String; void get_next(String T,int *next) { int i = 1; int j = 0; next[1] = 0; while(i < T[0]) { if(0 == j || T[i] == T[j]) { i++; j++; next[i] = j; } else { j = next[j]; } } } /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main() { char str[255] = "ababaaaba"; int next[255]; int i = 1; str[0] = 9; get_next(str, next); for(i=1;i<10;i++) { printf("%d ",next[i]); } return 0; }

                结果为

                                         

                                                                               获取next数组的结果图

    2,KMP算法的实现

                   

    //返回子串T在主串S第pos个字符之后的位置 int Index_KMP(String S,String T,int pos) { int i = pos; int j = 1; int next[255]; get_next(T,next); while(i<=S[0]&&J<=T[0]) { if(S[i] == T[j]) { i++; j++; if(T[i]!=T[j]) { next[i] = j; } else { next[i] = next[j]; } } else { j = next[j]; } } if(j>T[0]) { return i - T[0]; } else { return 0; } }                            

                                      

                                     

    
    转载请注明原文地址: https://ju.6miu.com/read-34484.html

    最新回复(0)