程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 最長公共子字符串

最長公共子字符串

編輯:關於C語言

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

注意到,設給定字符串為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”為例,表的構造方式如下:

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











		
		

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved