《數據結構和算法》之KMP算法

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


                           

                                  

                                 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章