實現順序串的各種模式匹配算法


目的:掌握串的模式匹配算法(BF和KMP )設計

內容:編寫一個程序exp4-3.cpp,實現順序串的各種模式匹配運算,並在此基礎上完成以下功能:
1、建立目標串s="abcabcdabcdeabcdefabcdefg"和模式串t="abcdeabcdefab";
2、采用簡單匹配算法求t在s中的位置;
3、由模式串t求next數組值和nextval數組值;
4、采用KMP算法求t在s中的位置;
5、采用改進的KMP算法求t在s中的位置;

寫在前面

今天學習了如何對順序串相關的算法,主要是看老師的PPT,問題主要分兩方面:

  1. 算法的理解
  2. 算法的實現
    以下主要就從這兩個方面進行討論

算法的理解

這道題目主要涉及的算法有BF,KMP。這兩個算法都是用來判定模式串t是否為目標串s的子串問題,其中BF算法感覺還挺簡單的,就是從s的每一個字符開始依次與t的字符進行匹配
匹配過程如下:

  1. \[S: \color{red}a\quad a\quad a\quad a\quad a\quad b \]

\[T:\color{red}a\quad a\quad a\quad b \]

此時i=0,y=0 s[0]=t[0]
i,j繼續后移,即i++, j++,直到出現s[i]≠t[j]
2. $$S: a\quad a\quad a\quad \color{red}a\quad a\quad b$$

\[T:a\quad a\quad a\quad \color{red}b \]

此時i=3,y=3 s[3]≠t[3] 匹配失敗
i回退,j重置為0(i=i-j+1,j=0)
循環執行1,2步
3. $$S: a\quad a\quad a\quad a\quad a\quad \color{red}b$$

\[T:a\quad a\quad a\quad \color{red}b \]

此時i=6,y=4 s[6]=t[4] 匹配成功!


總的說來,BF算法的關鍵在於匹配失敗時對i,j的處理。

算法的實現
//BF算法
int BF(SqString s,SqString t)
{
   int i=0,j=0;
   while (i<s.length && j<t.length )
   {
       if(s.data[i]==t.data[j] )
       {
           i++;
           j++;//繼續匹配下一個字符,依次匹配
       }
       else
       {
           i=i-j+1;//主串的指針回溯
           j=0;
       
       }//進行下一次匹配
   }
         
   if(j>=t.length )
      
   return (i-t.length );//返回匹配的第一個位置的下標,因為是依次進行匹配,所以最終i的值會有包含字串t的長度。
   else return (-1);
      
}

在閱讀這段代碼的時候while語句里的循環條件:while (i<s.length && j<t.length )不是很好理解,后來仔細檢查發現i,j都是從0開始,那么它們代表的是字符串中字符位置的下標,取
0--(length-1)

//主函數
int main() {
    SqString s,t;
    
    char a[]="abcabcdabcdeabcdefabcdefg",b[]="abcdeabcdefab";
    StrAssign  (s,a);
    StrAssign  (t,b);
    
    cout<<BF(s,t)<<endl;//輸出結果

//類型聲明,自定義函數
#define MaxSize 100
typedef struct 
{
    char data[MaxSize ];
    int length;
}SqString;//此為非緊縮存儲格式

void StrAssign(SqString &s,char cstr[])
{
    int i;
    for(i=0; i<(int)strlen(cstr); i++)
        s.data[i]=cstr[i];
    s.length=i;
}//字符串的生成

運行結果如下:

上面結果是BF算法,KMP算法,改進的KMP合起來的,雖然運行出結果了,但是對其中KMP算法部分還不是很理解,所以就沒貼上相關代碼。


KMP算法的初步理解

既然都是匹配字符串,第一步都是相同的,置$$i=0,j=0$$,對比BF算法,唯一的區別的地方就是在s[i]≠t[j]時(即匹配失敗時)對i,j處理的不同

此時,在t[j]字符前若找到k個字符使得
\(t_0t_1...t_{k-1}=t_{j-k}t_{j-k+1}...t_{j-1}t_j\)
即t[j]前有k個字符與t開頭的k個字符相等,說明t[j]字符前已有k個字符被成功匹配,
下一趟應從t[k]開始匹配,即置j為k(next[j]=k)

初讀這段話,感覺真的是雲里霧里,難以理解,怎么就匹配成功了呢?沉思許久,終於找到一個合理的解釋
將上面那段話翻譯一下:
s[i]前有k個字符與t開頭的k個字符相等,說明t開頭的k個字符被成功匹配,因為此時s[i]與t[j]前的字符是已經匹配好了的。


小結

至此KMP算法的核心思想總算初步搞明白了,只是還有許多細節的地方感覺不是很懂,在算法實現的時候對求next數組部分感到難以理解,看來還是沒有理解透徹,"革命尚未成功,同志仍需努力"呀

寫在最后

這是筆者第一篇關於學習記錄的博客,在寫作過程遇到了許多問題,好在總算完成了,因為記憶力不好,希望以這種方式記錄下自己的思考過程。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM