目的:掌握串的模式匹配算法(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,問題主要分兩方面:
- 算法的理解
- 算法的實現
以下主要就從這兩個方面進行討論
算法的理解
這道題目主要涉及的算法有BF,KMP。這兩個算法都是用來判定模式串t是否為目標串s的子串問題,其中BF算法感覺還挺簡單的,就是從s的每一個字符開始依次與t的字符進行匹配
匹配過程如下:
-
\[S: \color{red}a\quad a\quad 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$$
此時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$$
此時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數組部分感到難以理解,看來還是沒有理解透徹,"革命尚未成功,同志仍需努力"呀
寫在最后
這是筆者第一篇關於學習記錄的博客,在寫作過程遇到了許多問題,好在總算完成了,因為記憶力不好,希望以這種方式記錄下自己的思考過程。