在c/c++語言程式設計過程中,一般的字串搜尋操作都是通過標準庫的strstr()函式來完成的,這在通常的情況下,因為字串的搜尋操作不多,並不會產生效率問題。實際上,這個函式的時間複雜度不容樂觀。如果要從長度為n的字串中查詢長度為m的子字串,那麼這個strstr()函式的最壞時間複雜度為o(n*m),可見,隨著子字串長度m的增大,strstr()函式的時間複雜度也相應地成倍增加,有沒有更加高效的演算法呢?
kmp(knuth-morris-pratt)演算法通過預先計算模式字串中相應字元處的回溯索引,避免了模式匹配時不必要的回溯操作,從而提高了效率,將時間複雜度變成了o(m+n)。至於更加詳細的內容,請教google老師是個不錯的主義,其中「kmp演算法詳解」這篇文章講解的比較透徹,值得一看。
kmp演算法因為要儲存每個字元的回溯索引,所以空間複雜度會略微有所增加
sizeof(idx)*length(pattern)
另外,當n比較小時,建立回溯索引所引入的o(m)個時間複雜度也許並不輕鬆。這些條件致使kmp演算法適用於n和m都比較大,且字串搜尋操作比較頻繁的環境,例如:網路入侵檢測系統和qos系統等。
實際上linux 2.6版核心從2.6.14開始就引入了名為string的iptables匹配(match)模組,他提供有kmp、bm(boyer-moore)和f**(finite state machine)演算法,可以實現基於關鍵字的網路過濾。
在學習這個演算法的過程中,將linux核心中的實現**搬到了使用者空間:
#include
#include
#include
#include
void kmp_init(const char *patn, int len, int *next)
}int kmp_find(const char *text, int text_len, const char *patn,
int patn_len, int *next)
return -1;
}int main(int argc, char *argv)
next = calloc(strlen(argv[2]), sizeof(int));
kmp_init(argv[2], strlen(argv[2]), next);
printf("next array:/n");
for (i = 0; i < len; i ++)
printf("/t%c", argv[2][i]);
printf("/n");
for (i = 0; i < len; i ++)
printf("/t%d", next[i]);
printf("/n");
pos = kmp_find(argv[1], strlen(argv[1]), argv[2], strlen(argv[2]),
next);
printf("find result:/n");
if (pos < 0) else
return 0;
}
字串匹配之kmp
kmp主要就是計算字首函式e q max return m void kmp char s,char p int n strlen s int m prefixcomp p,e int k 0 for int i 1 i n i putchar n 習題 試說明如何通過檢查字串pt的字首函式e,來確...
字串匹配之KMP演算法
以前零零散散做了些kmp的題目,一直也沒找出時間整理,這一段又開始研究字串了,就順便把kmp整理了一下。廢話不說了,我們直接入題。說到kmp,首先應該知道,它是一種字串查詢演算法,因為是由乙個姓k,乙個姓m和乙個姓p的人聯合發表的,所以就叫kmp演算法了。kmp演算法是一種線性時間的的字串匹配演算法...
演算法 字串匹配之KMP
說人話就是 比如有乙個字串 bbc abcdab abcdabcdabde 我想知道,裡面是否包含另乙個字串 abcdabd 許多演算法可以完成這個任務,kmp演算法是最常用的之一。首先對於上面的 比如 我們首先要針對搜尋詞 abcdabd 算出一張 部分匹配表 接下來就很簡單了,將字串和搜尋詞都從...