Leetcode28 字串的匹配(KMP)

2022-07-20 02:24:16 字數 2866 閱讀 9228

題目: 題目的本質是給定兩個字串str1,str2,求str1中的str2串開始的地方,即字串的匹配,kmp演算法

思路:時間複雜度為o(m + n),空間複雜度為o(n),原串的長度為m,子串的長度為n

kmp演算法的本質是根據子串的next值求解的,所以首先講解next值得求法:

字串的next值的求解方法:

next[i]的含義是:以i-1位置結尾的字串與以0位置開始的字串的最長匹配

1. 建立乙個與子串大小相同長度的int型陣列next

2. next值中的next[0] = -1, next[1] = 0,這是一定的。下來求2 - 串尾的每個位置的next值。假設此時求next[i]的值:由於next[i]的含義是以i-1位置結尾的字串與以0位置開始的字串的最長匹配,而此時我們已經求除了i-1位置的next值,next[i - 1]含義是以i-2位置結尾的字串與以0位置開始的字串的最長匹配。我們使用cn表示與以i-2結尾的字串的匹配長度所以next[i - 1] = cn

a)如果i-1位置的值等於cn+ 1位置的值,則next[i] = next[i -1] + 1;由於next[i - 1]匹配的是0~cn和某個地方到i - 2, 因此如果cn + 1位置的值和i -1位置的值相等,則next[i] = cn + 1;

b)  否則 ,判斷next[i - 1]的值是不是大於0,大於0表示前面有某個位置還有匹配的可能性,即next值回退過程,cn =  next[cn]

c) 否則,表示cn = 0,即回退到第乙個位置了,則next[i] = 0;

如上圖所示: 我們來回顧一下next值的定義:next[i] = 以i-1位置結尾的字串與以0位置開始的字串的最長匹配

假設此時需要求i位置的next值,而我們已經知道next[i-1]的值,是從[0,z]和[i-2 - z, i-2]的匹配,長度為z,即next[i -1] = z;此時:

1)如果z的下乙個位置w的值和i-1的值相等,則就有了[0, z + 1] 和[i-2-z, i - 1]的匹配,該匹配就是next[i] 的值;

2)如果w = z + 1位置的值不等於i-1位置的值,則表示匹配的長度會比z短,而next[i - 1] = z, 此時我們要求的是next[z]的值:假設next[z] 的匹配為[0, x]和[z - 1- x, z-1], 同理,若y = x + 1位置的值與i - 1位置的值相等,則next[i] = next[z] + 1,若y位置的值與i-1位置的值不相等,則繼續向前回退,直到next[i] = 0;

證明過程:

此時next[i] = [0, x]長度,next[i]的長度為什麼不可能長於x?

[0, z] = [i -2 - z, i - 2], [0, x] = [z - 1 - x, z - 1], 由於[0, x] ∈[0, z], 因此[0, x]∈[i -2 - z, i - 2],再回想一下next[i]的定義,因此只要x+ 1位置的值與i-1位置的值相等,則可以計算出next[i]的值;

我們此時假設next[i]的長度為[0, q]的匹配,q > z + 1,則 i-1和q位置,i-2和q- 1位置的值.....都是相等的,那麼next[i -1] 的值就為[0, q]的匹配,q > z , 顯然與」最長匹配原則「不一致;

我們再假設next[i] 的長度為[0, x]的匹配,z > q > x + 1, 則 i-1和q位置,i-2和q- 1位置的值.....都是相等的,那麼next[i - 1]的值就是[0, q]的匹配,而q < z,因此與」最長匹配不相等「

kmp的匹配過程:

1. 從頭開始匹配,如果相等,則子串和原串都繼續向後

2.如果在子串的某個位置i不相等,則表示i-1前面的都已經匹配上了,所以子串和原串都不要回退,由於next[i] 表示的是i-1位置結尾的字串和以0位置開始的字串的最長匹配,所以,如果next[i] = -1,則表示原串與子串的第乙個字元否沒有匹配,則原串位置向後移動,否則 只需要從子串的next[i]位置與原串繼續比較即可。

假設此時比較到子串的i位置,對應主串的s+ 1位置不匹配,表明[t,s]和[0, i -1]是匹配的,則根據next[i]的含義,可以得出子串中[0, x1]與主串[s1,s]是匹配的,因此下一次只需要從字串的x1+1位置和s+ 1位置進行比較即可;

**如下:

1

public

class

solution

20else

if(next[nindex] == -1) //

表示與子串的第乙個字元就沒有匹配上,則主串自己向後移動

2124

else

//直到nindex - 1都匹配上了,所以子串不需要從頭繼續,只需要從next[nindex]位繼續匹配即可

2528}29

return nindex == nlen ? hindex - nindex : -1; // 如果匹配到子串的結尾,則返回此時主串與子串的位置差,即為開始匹配的地方30}

31public

int calnext(string needle)32;

35int next = new

int[needle.length()];

36 next[0] = -1;

37 next[1] = 0;

38int cn = 0;

39int pos = 2;

40while(pos

4149

return

next;50}

51 }

28 字串的排列

題目 輸入乙個字串,按字典序列印出該字串中字元的所有排列。例如輸入字串abc,則列印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。解題思路 遞迴呼叫 遞迴演算法的四個特性 1.必須可以達到終止條件,否則會陷入死迴圈 2 子問題在規模上比原問題小 3 子問題可...

面試題28 字串排列

輸入乙個字串,按字典序列印出該字串中字元的所有排列。例如輸入字串abc,則列印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。結果請按字母順序輸出。輸入描述 輸入乙個字串,長度不超過9 可能有字元重複 字元只包括大小寫字母。1 class solution 1...

字串 leetcode 43 字串相乘

給定兩個以字串形式表示的非負整數 num1 和 num2,返回 num1 和 num2 的乘積,它們的乘積也表示為字串形式。示例 1 輸入 num1 2 num2 3 輸出 6 示例 2 輸入 num1 123 num2 456 輸出 56088 說明 num1 和 num2 的長度小於110。nu...