kmp的演算法分析
kmp解決問題:清除bf演算法中主串s指標出現的回溯情況,即當主串s和子串t在某個字元不匹配的時侯,主串s的指標位置不變,改變子串t的指標位置,使主串和子串的字元匹配
演算法思路:建立乙個next陣列,當出現主串字元與子串字元不匹配時,將模式串t的指標 j 移動到next[j]的位置,i位置不變(即沒有回溯),進而使得主串字元和子串字元匹配,進行下一步的匹配
next陣列的建立思路
按照之前的描述,當主串從第pos位置開始字元匹配,一直向右移動到第 i 位,同時子串也一直向右移動到第 j 位( i 和 j 的值並不相同,因為主串從第pos位置開始的,若pos==1,則有 i == j,若不相等,則j == i -pos +1)這時s [ i ]和t [ j ]不相同,由kmp演算法,子串t的指標 j 移動到next[ j ]的位置,假設next [ j ] = k,移動到k位置後,主串和子串達到匹配後,主串繼續向右移動。
現在我們分析 k 和 j ,由於子串從 j 位置移動到了k位置,所以我們可以知道主串從pos位置到 j-1位置的字元與子串匹配,而當子串移動到k位置匹配,同樣可以知道,主串從si向左數 k 位字元都會與子串t匹配
為了方便理解,我們假設pos=1(這並不影響演算法的思路,因為pos= i - j +1)
這是沒移動前的狀態,si !=tj
其實s1不應該是和t1對其,但是為了使後面si和tk對齊,只能這樣顯示,注意!其實上圖的s1不和t1相等
上面第二個是移動後的狀態,si==tk
這樣有什麼作用呢,其實這可以幫助我們構建next陣列。由於移動前,子串前 j-1個字元與主串從i位置往前數 j個字元匹配,即從pos-j+1開始直到 i-1位置匹配。
同理,移動後,主串從pos-k+1開始匹配直到 k 位置匹配,所以移動後從pos-k+1到k-1都匹配(前k項都匹配,所以前k-1項肯定匹配)
由於主串是一直不變的,由於移動前後主串 i 位置前若干個字元同時與移動前後子串相同
所以我們可以得到子串前k-1個字元會和子串後k-1個字元相等(若不太理解,可以動手畫一下方便理解,可以就只用乙個主串,畫兩個相同的串代表移動前後的串,對齊主串畫,這樣會容易理解一點)由於next[ j ]=k,所以第 j 位的next陣列值等於子串長度是j-1的真字首子串中,真字首子串和真字尾子串中最長相同部分的子串長度+1(注意是真字首子串的真前字尾子串相同部分的最長子串長度加一,而且第 j 位的值是長度為j-1位的真字首子串產生的值)
因為第 j 位要看 j-1 位的真字首子串,但是當 j=1時,j-1=0,所以next[ 1 ]=0(這是字串下標從1開始,若從0開始,應該是-1),同樣的當j=2時需要看長度為1的真字首子串(注意時真字首)所以最大長度是0,然後按照next陣列的建立規則,最大長度加一,所以next[ 2 ]=1(這個同樣,若是字串下標從0開始,這應該是0),這兩個很特殊,所以對於任何乙個子串來說,next陣列的第1位和第二位都是確定的。
//kmp演算法,字串下標從0開始
//devc++6.0
void kmp(string s,string t,int index)
else
k=next[k]; //移動到next[ k ]位置繼續比較
} return ;
}
演算法 KMP演算法完全解析(C語言實現)
kmp演算法所做的事情,就是在字串中尋找子串。比如ilovecode這個字串中,我們可以搜尋到love這個子串。但如果用回溯的暴力方法尋找子串 即兩個for迴圈 雖然思路簡單,但是時間複雜度為o m n 借助kmp演算法,可將複雜度降為乙個迴圈,增進了效率。1 字首和字尾的概念 字首 指的是從首字元...
Go語言實現kmp演算法(一)
kmp演算法分為兩部分,第一部分為next陣列的獲取,第二部分為使用next陣列進行匹配,兩部分採用的思路大體相同。該演算法有多種方式實現,此處介紹移動的方式實現,還有教科書上的手算方法實現,即計算最大前後子串長度,將next陣列向後一位,首位置為 1,則匹配過程中移動距離等於 當前index in...
KMP演算法詳解C 實現
kmp演算法是判斷兩個字串str1中是否包含與str2相同的子串。next陣列概念 kmp演算法最關鍵的就是next陣列。next陣列就是針對str2串中每個字元前的子串中存在的字首與字尾匹配的最長長度。假設str2為 abababca j 0,字元str2 j a,a前沒有字串,預設為next 0...