首先先來看乙個問題,給出兩個字串,s和t
問t在s中出現了多少次,不允許重複,但允許相互有相同部分。
首先想到的肯定是暴力,可以想到,從s的第乙個字元開始,看是否和t相等,然後向後移,統計有多少個相等,那麼時間就是o(
n×m)
當然,這個速度是非常慢的,如果兩個串的長度很長,或者有多組資料,自然就超時了。
顯然,在匹配的時候,如果遇到不相等的情況,移到下一位的時候,有很大的機率不會相等,那麼可以用乙個
next
陣列,記錄失配的時候,向右移幾位就可以讓前面的依然匹配。這就是kmp演算法的核心。
這時候就可以這樣做:
首先從第乙個字元開始,如果相等那麼向後匹配,如果失配那麼就跳到
next
位置。如果長度與t的長度相等,那麼計數器就加1
那麼,有了next,就很容易計算答案了,以下為**
int kmp()注意乙個很重要的東西:if (s[i] == t[k])
if (k == lent)
}return ans;
}
next
在乙個庫中是乙個函式,最好不要呼叫,所以寫成了
_next
那麼,如何求
next
呢? 其實,求
next
也相當於是乙個在t之中與t匹配的樣子,先來看看**。
void get__next()
if (t[i] == t[k])
_next[i]=k; // 記錄
}}
看起來和匹配很像對不對……
事實上,的確和匹配很像。
可以發現,
next
記錄的就是t的乙個字首的結尾和t的開頭最多能夠匹配的位數。匹配時,k記錄的就是s的字首和t的開頭能夠匹配的位數。
同時,求到k的時候,k前面的
next
都是求好的。
所以類似這樣的方法,去用t去匹配t,直接套用前面的匹配過程。
最後再分析一下時間複雜度。
既然它這麼神奇,
那麼時間複雜度肯定比o(
n×m)
要小,所以它的時間複雜度應該是線性的,於是來證明一下.
在匹配的時候,在s串中,k每一次
while
至少前進1,所以最多前進n次,而且最多會後退n次,因此匹配部分的時間複雜度應該為o(
n)那麼,求
next
類似,需要o(
m)的時間,所以最後總共需要o(
m+n)
的時間
這樣,kmp就順利地學完了……
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的第乙個字元,依次比較下去,直到得出最後的匹配...