kmp演算法我是看july部落格學習,這裡只是做個筆記,詳細內容見july的blog:
kmp演算法的用途:有乙個文字串s和乙個模式串p,現在要查詢p在s中的位置。暴力匹配演算法需要對文字串s進行回溯,kmp演算法就是讓文字串不回退,只需要移動模式串j即可。
kmp演算法大體思想:就是當s[i]==p[j]時,我們對i++,j++;如果不相等則令j=next[j]。這裡next[j]為j字元之前的字串中有多大長度的相同字首字尾(注意字首不能包含最後乙個,同時字尾不能包含第乙個,所以aaaab的next陣列為-10123)。相當於將模式串向右移動了j-next[j]位。next陣列的求解採用的是迭代的思想,需要分p[j]是否等於p[k]兩種情況以求得next[j+1]。
時間複雜度:暴力匹配演算法的時間複雜度為o(n*m)(最差的情況). kmp演算法的時間複雜度為o(n+m), 因為match串(模式串)最多向右推動了長度就為n,而字串本身不回退。這裡n和m分別為文字串和字串的長度。next時間複雜度為o(m),可以這樣理解:迴圈中有兩個變數,j和k,而j與j-k每次都是增加的或者乙個不變,故最多迴圈2m次,時間複雜度為o(m)
next陣列求解:next[0]=-1,k=-1; next陣列通過**遞推求得,假定next[j] = k求next[j+1],先判斷p[j]是否等於p[k], 如果相等則令next[++j] =++k; 否則令k=next[k]《這個不太好理解》繼續迭代。時間複雜度為o(m).
k=next[k];為什麼不是k--?給個例子dadcdadde, 當求e的next值時就會出錯。k=k-1的話求到的是倒數第二個d,則為next[e]=2+1=3這裡是dad明顯不對,然後再看abdabcabdabde據對稱性得k=next[k]是正確的
優化next陣列:next陣列主要針對模式串abab的情況,比如在文字串abacab中尋找,此時當p[3]與s[3]匹配失敗時,則將abab向右移動兩位,此時p[1]仍然等於b,匹配必然失敗,優化的next陣列主要解決這個問題。當p[3]=p[next[3]]時 令next[3]=next[next[3]]。看**則很好理解了。
以上則是個人理解筆記,下面給出具體**:
1:kmp演算法**
#include using namespace std;
// 獲取next陣列
void getnext(int *next, const char *p) // 已知next[j] 求next[j+1] 分p[j]是否等於p[k]兩種情況 迭代的思想
else }}
// 獲取優化next陣列
void getnextopt(int *next, const char *p) // 已知next[j] 求next[j+1] 分p[j]是否等於p[k]兩種情況 迭代的思想
else }}
// kmp 演算法
int kmpsearch(const char *p, const char*s)
else if(j == 0) // 這樣對於首字元不滿足的時候直接優化
i++;
else
} delete next; // 釋放動態申請的陣列
if(j == ptrlen)
return i - j;
else return -1; }
int main()
2:暴力匹配演算法——又被稱為樸素字串匹配演算法(***** string match)
#include using namespace std;
int violencesearch(const char *p, const char *s)
else
} if(j == ptrlen)
return i - j;
else return -1;
}int main()
3:求最大長度表演算法
也可以由最大長度表來求next陣列,通過最大長度表各項向右移動一位,然後初值賦值-1即可,但是這種方法求最大長度表所消耗的時間為o(n^2)
// 針對乙個字串獲得最大長度的相同字首字尾
int getmaxfix(const char *p, int plen)
else
} }return k;
}// 獲得最大長度表
void getmaxtable(const char *p, int *table)
}
kmp演算法的變形
即求模式串在文字串中出現的次數。這裡演算法的基本思想就是求出模式串的公共字首字尾即next[s.size()],當j==s.size()的時候讓j=next[s.size()]就可以了。就好比模式串abcdea,當結束的時候j=6,此時next[j] = 1,故讓j=1繼續去匹配,即前面有k位和字串中是相同的。
**如下:
#include #include using namespace std;
#define pmaxsize 10010
void getnext(int *inext, const string s)
else k = inext[k]; }}
int kmpalg(const string &p, const string &s)else if(j == 0)
i++;
else
j = inext[j];
if(j == p.size())
} delete inext;
return count;}/*
//freopen是被包含於c標準庫標頭檔案中的乙個函式,用於重定向輸入輸出流。
該函式可以在不改變**原貌的情況下改變輸入輸出環境,但使用時應當保證流是可靠的。
*/int main()
return 0;}/*
input:5ha
hahaha
wqnwqn
adaadadada
bababb
bababababababababb
dadaddaadaaddaaadaad
output:31
310*/
KMP演算法筆記
無聊開啟vjuge看了一眼,看到有乙個比賽是ac自動機,開啟看看順便xuexi一下子。需要 kmp複習一下感覺全忘了。附兩篇參考資料 和乙個練習題 include include include include include include include include include incl...
KMP演算法筆記
1.kmp演算法用於字串匹配。2.最直觀的字串查詢,是用兩次迴圈遍歷,演算法複雜度0 m n m為待查字串,n為需要查詢的子串。3.kmp演算法的目的為減少n維度。4.include include using namespace std void getnext const string ptr,...
KMP演算法筆記
kmp演算法是一種快速的字串匹配演算法,我們先從暴力字串匹配演算法講起看怎麼對其優化得到kmp演算法。這篇文章 1 暴力字串匹配 有如下兩個字串 a abcabbcabc 和b adfabcabccabcadbcabca 我們要在b中找到a的匹配位置,暴力匹配的做法就是 把a的第乙個元素與b的第乙個...