1. 程式人生 > 實用技巧 >KMP演算法總結

KMP演算法總結

KMP演算法是一種效能比較好的字串匹配演算法。
首先,在理解效能比較好的KMP演算法之前,我們首先要先想一下對於字串匹配的樸素暴力做法我們一般是怎麼做出來的。
舉個例子:
對於主串s[n],子串p[m]。我們要計運算元串p[m]在主串中出現的位置的話。核心程式碼一般是下面這個樣子的:

for(int i=1;i<=n;i++)//關於主串
{
     bool flag=true;//判斷此時要匹配的兩個字元是否相等,相等即為true;
     int k=i;//k對i的值進行記錄
     for(int j=1;j<=m;j++)//關於子串
     {
          if(s[k]!=p[j])
          {
              flag=false;
              break;//跳過本次迴圈,p從頭開始與主串s的下一個字元進行比較
          }
          else
              k++;
     }
    if(flag)//說明匹配成功
      cout<<i<<endl;//輸出字串匹配開頭的成功位置
}

這種做法的時間複雜度是O(mn)的。

這種做法最大的時間浪費體現在每一次匹配不成功,子串p都要從頭開始與主串的下一個字元進行匹配。

如果我們能夠對子串進行預處理,記錄下子串每個位置字尾和字首相等的最大長度,這樣我們每次在第二重迴圈中對j開始處理時就可以直接從當前位置的長度開始,而不必每次都從1開始,我們把每個位置的這些長度值所組成的陣列叫做next陣列。
我們求next陣列的核心程式碼如下:

for (int i = 2, j = 0;i <= m;i++)
	{
        //next[1]一般情況都是0,字首和字尾相等的不能夠是其本身
		while (p[j + 1] != p[i] && j)    j = next[j];//字尾不相等時j回到上一次與字尾相等的位置
		if (p[j + 1] == p[i])    j++;//當字尾和字首的字元相等時,j++,繼續進行匹配
		next[i] = j;
	}

KMP演算法講解_1