最長公共子字串

2022-04-10 09:42:48 字數 1875 閱讀 5986

關於題目理解,請注意和最長公共子串行的區別,最長公共子字串的解法是動態規劃,但是比較難想到表的構造方法。

注意到,設給定字串為str1 和 str2 ,二者的長度分別是 len1 和 len2 ,那麼解空間大小之多是len1*len2?(假設最長公共子字串為substr_common,那麼substr_common在str1 中的結束位置或者起始位置只有len1種選擇,而在str2中則最多len2種選擇,故解空間最大為len1*len2)。對於解空間中的每乙個解都對應著自己的長度,因為一旦結束位置都確定,即意味著公共子字串找到了。

如果用蠻力法做的話,遍歷解空間需要時間複雜度為o(len1*len2),然後確定每個解的長度需要的時間是o(min(len1,len2)),所以基本上是個o(n3)的演算法,顯然不妥。

前面說過,這道題可以用動態規劃來做,動態規劃最關鍵的是找到最優子結構,一般來說,最優子結構意味著問題可以找到一種遞迴的,不斷縮小問題規模的解決方式,與分治法不同,動態規劃的小問題之間有重疊,但是這個問題好像不是那麼好找到一種遞迴的表達形式。

要縮小問題規模,一種最簡單的想法肯定是縮小str1規模,或者縮小str2規模,或者二者同時縮小,而縮小的方式肯定是增減元素了,能用動態規劃做必定有個自底向上的過程,很少有直接二分的, 直接二分是分治法的策略,所以增減一般在頭尾增減,以此題為例,為保持一致性,在分析題目的過程設兩個字串都由尾部向頭減少,而在解決問題的過程中是由頭部向尾部增加。我們可以構建一張表count[len1][len2] , 其中count[i][j] 表示如果公共子字串在str1的第i個位置結束,在str2的第j個位置結束時公共子字串的長度。從底向上開始構建這張表,下面是增減的描述:假設目前需要計算count[i][j],有以下幾種情況:

1. str1[i] == str2[j] : 此時count[i][j] = count[i-1][j-1]+1

2. str1[i] != str2[j] :

很顯然,以i,j為結束點的解 count[i][j] = 0 .

因此,一旦知曉了count[i-1][0,….,len2] ,count[i][0,….,len2]可以順序獲得,以str1 = 「1234」, str2 = 「2345」為例,表的構造方式如下:

只要在構建表的過程中記住當前最長的子字串長度和結束位置,就可以很輕易地列印出最長公共子字串,與之相對應的**如下:

author : lipan
date : 2013.07.29
email : [email protected]
*/
#include

#include

int lcs_substring(char *str1,char *str2,int str1_len,int str2_len);
int main()
int lcs_substring(char *str1,char *str2,int str1_len,int str2_len)
else
if(maxsubstrlen//輸出最長公共子字串
printf("the longest common substring is :");
for(int i = maxsubstrw-maxsubstrlen+1;i<=maxsubstrw;i++)
return maxsubstrlen;
}

最長公共子字串

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

最長公共子串,字串

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

最長公共字串和最長公共子串行

給出兩個字串,找到最長公共子串,並返回其長度。建立乙個矩陣來儲存兩個字串出現相同字元的地方,比如 abccd 和 abcefc 就有 abccd a10000 b02000 c00300 e00040 f00000 c00100 這樣就有每次遇到相等的都加上下他的斜上方的位置的值,然後使用乙個max...