字串匹配問題分析
(1)字串匹配一般演算法 與 kmp演算法比較:
一般演算法:從父串的第乙個字元開始與子串的第乙個字元開始比較:
1、若相等,再比較各自的第二個字元,依次迴圈進行,直到整個子串結束。在子串沒有完全匹配完之前,若有乙個字元不相等。請參考以下若不相等。
2、若不相等,從父串的第二個字元開始與子串的第乙個字元開始重新逐個比較。如此迴圈,直至匹配到 完全子串 或 父串結束 程式結束。
kmp演算法:觀察分析子串的特點,我們很容易的發現子串中也存在相同的子串,如「abcdabd」。
子串的前兩位(str[0]、str[1])字元ab與第
五、六位(str[4]、str[5])的ab字元就是相同的子串。
一般演算法執行子串與父串匹配的過程中,假設當匹配到子串第七位(str[6])處發現不相等時:
一般演算法的做法:傻瓜式的用子串與從本次迴圈父串開始位的下一位重新執行新一輪逐位迴圈匹配。
kmp演算法的做法:結合子串的特徵,從開始位 + 4索引處重新又開始一輪的迴圈匹配。
或者,kmp演算法的做法也可以理解為:從父串的匹配失敗位開始與子串的第三位(str[2])重新新一輪的匹配。
(2)kmp演算法匹配過程如下:
2.1、待匹配父串、子串:
2.2、從父串第乙個字元開始,b與a不匹配。
2.3、逐位進行匹配,b與a不匹配。
2.4、中間的迴圈匹配省略。直接到如下圖所示,發現空字元與d不匹配。
2.5、一般方法做法,從父串的第六個字元b開始,與子串的第乙個字元a重新開始下一輪匹配。
kmp演算法的做法如下,直接從父串的失敗位空字元與子串的第三個字元c開始作比較,發現不匹配。
2.6、從父串的失敗位空字元開始,與子串的第乙個字元a開始,逐位重新開始迴圈匹配。
2.7、上一步發現空字元與a不匹配。那麼,從主串空字元的下一位a開始與子串的第乙個字元a進行新一輪迴圈匹配。
2.8、結果發現c字元與d字元不匹配。那麼,kmp演算法直接用失敗位字元c與子串的第三個字元c開始匹配。
直至子串完全匹配。程式結束。
kmp演算法是對子串進行規律性的分析後減少不必要迴圈過程的方法。
各種演算法c++實現
演算法實現以及測試程式如下:
#include #include以上實現。#include
#include
//第一種最普通的方法
//思路分析:
//(1) 確定父串與子串的長度大小
//(2) 定位父串,進入迴圈
//(3) 定位子串,進入迴圈
//(4) 開始逐個與父串比較,若有乙個不相等,break;
//(5) 若完全匹配則成功
//(6) 返回索引
int findstr1(const
char *si, const
char *sd)
}if (j >=n)
return
i; }
return -1;}
//第二種簡單的方法(簡稱:巧借驅動)
//思想分析:
//(1) 定位父串與子串的索引
//(2) 鎖定父串的索引指標,借子串的索引指標,遞進遍歷
//(3) 若相同,則子串索引向前
//(4) 否則,父串索引向前,子串歸位
//(5) 判斷sd的末尾指標的值;
//(6) 若相同,則返回鎖定的父串索引;否則,失敗
int findstr2(const
char *si, const
char *sd)
else
}if (sd[j] == '\0'
)
else}//
第三種簡單方法(第二種的思想)(簡稱:月亮走我也走)
int findstr3(const
char *si, const
char *sd)
else
}if (sd[j] == '\0'
)
else}//
第四種方法
void subnext(const
char *sd, int
next)
}if (i >=k)
else
}next[j] =k;
++j;
}}int findstr4(const
char *si, const
char *sd, int
next)
else
}if (sd[j] == '\0'
)
else}//
第五種方法
void subnext_kmp(const
char *sd, int
next)
else
}}void
main()
;
char str2 = ;
int pos1 =findstr1(str1, str2);
printf(
"pos1 :: %d\n
", pos1);
int pos2 =findstr2(str1, str2);
printf(
"pos2 :: %d\n
", pos2);
int pos3 =findstr3(str1, str2);
printf(
"pos3 :: %d\n
", pos3);
int* pnext = (int*)malloc(sizeof(int) * sizeof
(str2));
memset(pnext,
0, sizeof(int) * sizeof
(str2));
subnext_kmp(str2, pnext);
for (size_t i = 0; i < strlen(str2); ++i)
int pos4 =findstr4(str1, str2, pnext);
printf(
"pos4 :: %d \n
", pos4);
memset(pnext,
0, sizeof(int) * sizeof
(str2));
subnext_kmp(str2, pnext);
for (size_t i = 0; i < strlen(str2); ++i)
int pos5 =findstr4(str1, str2, pnext);
printf(
"pos5 :: %d \n
", pos5);
free
(pnext);
system(
"pause");
}//run out:
/*pos1 :: 15
pos2 :: 15
pos3 :: 15
-1 0 0 0 0 1 2 pos4 :: 15
-1 0 0 0 0 1 2 pos5 :: 15
請按任意鍵繼續. . .
*/
總結參見大牛的文章《 字串匹配的kmp演算法 》
good good study, day day up.
順序 選擇 迴圈 總結
KMP演算法 字串匹配
kmp演算法基本思想 我們在用常規的思想做 字串匹配時候是 如 對如 字元如果 t abab 用p ba 去匹配,常規思路是 看 t 第乙個元素 a 是否 和p 的乙個 b 匹配 匹配的話 檢視各自的第二個元素,不匹配 則將 t 串的 第二個元素開始 和 p 的第乙個匹配,如此 一步一步 的後移 來...
KMP字串匹配演算法
kmp核心思想 計算模式串的next陣列,主串的索引在比較的過程中不回朔 ifndef kmp h define kmp h class kmp endif include kmp.h include include include using namespace std int kmp calcu...
KMP字串匹配演算法
在介紹kmp演算法之前,先介紹一下bf演算法。一.bf演算法 bf演算法是普通的模式匹配演算法,bf演算法的思想就是將目標串s的第乙個字元與模式串p的第乙個字元進行匹配,若相等,則繼續比較s的第二個字元和p的第二個字元 若不相等,則比較s的第二個字元和p的第乙個字元,依次比較下去,直到得出最後的匹配...