字串 最長公共子串(兩個,多個)

2021-09-25 06:33:10 字數 1684 閱讀 8876

關於暴力解和動規說的最好的

空間複雜度 o(1) 還是左神的p225說的好。其實也沒什麼意思orz!

問題:有兩個字串str1和str2,求出兩個字串中最長公共子串長度。

時間複雜度:

假設兩個字串str1和str2的長度分別為x和y,則字串的子串個數分別為

n1 = x + (x-1) + ... + 1 = x(x-1) / 2

n2 = y + (y-1) + ... + 1 = y(y-1) / 2

所以,暴力求解法下,對比兩個子串是否相等,時間複雜度為o(x^2*y^2),即o(n^4)。

遍歷str1的每乙個子串a,然後str2.find(a)==string::npos 看str2裡面有無對應的子串,因為find用的是kmp,find的複雜度是y,所以總的複雜度是o(x^2*y),即o(n^3)

不用str.find 也能做到o(n^3)

不是遍歷str1的每乙個子串,而是把str1中以str1【i】為開頭,str1【str1.len()-1】為結尾的子串,跟str2中以str2【j】為開頭,str2【str2.len()-1】為結尾的子串,依次比較,找到兩個字串的最長公共字首,複雜度依舊是o(n^3)。

狀態轉移方程:

假設,兩個字串分別為

a = a1, a2, ..., ax

b = b1, b2, ..., by

我們定義dp[i][j]的含義是:必須把a[i-1]和b【j-1】當作公共子串最後乙個字元的情況下,公共子串最長能有多長。

常規動規思想:

另一種角度:

class longestsubstring 

}}

return res;}};

自然dp陣列的維度就是n維的,時間複雜度也是o(n^n),實際中自然不可能用這種方法的,那就是用字尾陣列做,不過這逼玩意屬實太難,假如面試碰到,跟他bb一下,就ok了

把n個字串的所有字尾,排序,假如n個字串的總長度是k,那麼字尾的個數是k,而排序假如用倍增演算法+基數排序,那時間複雜度是o(klogk),即使用快排,假如字串是隨機的,那其實也就是o(klogk)

最壞的情況: 快排每個字尾(n log n),但是這是字串,所以比較任意兩個字尾的複雜度其實是o(n),這樣一來就是接近o(n^2 log n)的複雜度,但是其實,假如是隨機的字串,比較任意兩個字尾的平均複雜度應該是o(1),因為一共就那麼幾個字元,比不了幾個字元就判斷出大小了。

然後還有幾個重要的性質:

1)任意1個子串都是某個字尾的字首

2)任意2個字尾(i,j)之間的最長公共字首,都是這一段相鄰字尾之間的最長公共字首的最小值,

即  lcp(i,j)=min(i而求相鄰兩個最長公共字首(即,裡面的height陣列)又有個優化,可以做到o(n)

搞出了這些之後,對於n個字串的最長公共字首,是字尾陣列中相鄰n項(得是分別來自n個不同字串)的最大公共字首,

最後的複雜度是o(k* logk)

n個字串的  具體的可以看看    

字尾陣列: 粗暴介紹 

性質2的證明 

比較圖形化的介紹: 

最後貼的** 很棒! 

最長公共子串,字串

目前,在各大 或者是,有著不少的關於這個問題的講解,但是目前覺得都不是很清晰明白!現在普遍的解法都是用動態規劃的方式來做這道筆試題。或者是經典的面試題。這裡我做乙個自認為比較清楚的講解。說到動態規劃很多人都不會感到很陌生。但是有多少知道動態規劃什麼?精髓在 這裡僅僅提供一些個人見解,首先,動態規劃不...

最長公共子字串

關於題目理解,請注意和最長公共子串行的區別,最長公共子字串的解法是動態規劃,但是比較難想到表的構造方法。注意到,設給定字串為str1 和 str2 二者的長度分別是 len1 和 len2 那麼解空間大小之多是len1 len2?假設最長公共子字串為substr common,那麼substr co...

最長公共子字串

描述 求兩個輸入序列的最長的公共子字串的長度。子字串中的所有字元在源字串中必須相鄰。如字串 21232523311324和字串312123223445,他們的最長公共子字串為21232,長度為5。輸入格式 兩行,第一行為第乙個字串x,第二行為第二個字串y,字串不含空格並以回車標示結束。x和y的串長都...