演算法其實並不難,但是講的費勁,看的也費勁……
**問題描述:**給兩個字串str和ptr,求str中是否有和ptr相同的子串並找出這個子串在str中的位置
這個問題的暴力演算法很好想:從頭開始乙個字母乙個字母地遍歷str,然後對照ptr是否是從這個位置開始的子串。而kmp演算法利用了前字尾的特殊性,簡化了時間複雜度。
(從o(mn)變為o(m+n))
ps:演算法思想可以參考:
戳我看敲好理解的kmp演算法鴨
(1)首先介紹字首字尾:如abcdef,字首就是a,ab,abc……而字尾就是f,ef,def……理解前字尾以後我們引入乙個陣列next,next中存放的就是到i這個位置(包括這個位置)之前前字尾相等且最長的情況。
如果不是很理解我們舉個栗子 (劃掉)例子 :在前面提到的**中的兩個字串
str:bbcabcdabababcdabcdabde
ptr:---------------------- abcdabd------------- (絕了,為什麼不能用空
格對齊,只好這樣了)
next[ptr]可以對應寫出:
next[1]=0
next[2]=0
next[3]=0
next[4]=0
next[5]=1(相同前字尾:a)
next[6]=2(相同前字尾:ab)
next[7]=0
可以看出:ptr在d前面的一串都適配了,但是d和c不適配。
那麼發現不匹配的時候,難道我們是將ptr位置直接++,然後繼續比對嗎?其實不必。
我們可以發現,ptr在d前面的序列abcdab中,字首ab和字尾ab是相等的,即next[6]=2。重點來了!!那麼我們可以直接把ptr從何前面移動到後面這個加粗的ab這裡。因為我們已經從next陣列中知道了在6這個位置,有乙個長度為2的字尾等於前面長度為2的字首。那麼就說明直接將ptr移到這個位置,剛好可以匹配。
移動4=6-2
即公式:要移動的位置=已經匹配的數x-next[x]
可能會有人有疑惑,比如說:
str:ab***ab***xxabc
ptr:ab***ab***xxabd
next[14]=2-------------↑這兒
那麼就把ptr:--------ab***ab***xxabd
為什麼ptr不直接跳過了中間的ab段而移動到了後面的ab段
其實可以舉個反慄,如果中間那段ab開頭的字串和ptr匹配,那麼就有更長的前字尾,就和之前定下的next[14]=2不符合了。
然後我們看怎麼求next。直接貼上**,這裡的next和上面的next不一樣。。這裡的next求的是到這個位置的最長長度前字尾-1!記住要減1!因為後面**從0開始計數,減一才能對應。
void
kmp_next
(char
*s)if
(s[k+1]
== s[i])
next[i]
= k;
}}
哇,看得我腦殼疼。
最難理解的應該是k=next[k]這一行。不方,其實這就是乙個回退操作
指路:next演算法
從求next開始那段,講得很清楚了
全**:
#include
#include
using
namespace std;
#define maxn 101
int nextt[maxn]
;void
cal_next
(string str)
if(str[k+1]
==str[i]
) nextt[i]
=k;}
}int
kmp(string str,string ptr)
return-1
;}intmain()
(1)如果len可以被len - next[len]整除,則表明字串s可以完全由迴圈節迴圈組成,迴圈週期t=len/l。
(2)如果不能,說明還需要再新增幾個字母才能補全。需要補的個數是迴圈個數l-len%l=l-(len-l)%l=l-next[len]%l,l=len-next[len]。
**:(1)關於next的求取
nextt[i]:
nextt[0]=-1
nextt[1]=0;
這兩個是固定的
i=1~n;訪問的是當前這個位置(注意!不是從0開始!)有多少個最大相同前字尾
這樣,雖然string是從下標0開始的,但是把它往後移了一位~
如果k=-1直接加一了
#include
#include
#define maxn 1000000+10
using
namespace std;
int nextt[maxn]
;void
cal_next
(string str)
nextt[
++i]
=++k;}}
intmain()
} cout<}}
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的第乙個字元,依次比較下去,直到得出最後的匹配...