動態規劃求解兩個字串的最大公共子串問題
阿新 • • 發佈:2019-02-18
最大公共子串長度問題就是:
求兩個串的所有子串中能夠匹配上的最大長度是多少。
比如:"abcdkkk" 和 "baabcdadabc",
可以找到的最長的公共子串是"abcd",所以最大公共子串長度為4。
下面的程式是採用矩陣法進行求解的,這對串的規模不大的情況還是比較有效的解法。
請分析該解法的思路,並補全劃線部分缺失的程式碼。
#include <stdio.h> #include <string.h> #define N 256 int f(const char* s1, const char* s2) { int a[N][N]; int len1 = strlen(s1); int len2 = strlen(s2); int i,j; memset(a,0,sizeof(int)*N*N); int max = 0; for(i=1; i<=len1; i++){ for(j=1; j<=len2; j++){ if(s1[i-1]==s2[j-1]) { a[i][j] = __________________________; //填空 if(a[i][j] > max) max = a[i][j]; } } } return max; } int main() { printf("%d\n", f("abcdkkk", "baabcdadabc")); return 0; }
【分析】DP
這裡使用動態規劃法求解串s1和s2的最大公共子串長度,a[i][j]表示串s1的前i個字元組成的串和串s2的前j個字元組成的串的最大公共子串的長度。
s1中的子串s1[0]..s1[i]匹配s2中的子串s2[0]..s2[j],在s1[0]..s1[i-1]和s2[0]..s2[j-1]已經匹配的情況下匹配長度+1,即a[i][j]=a[i-1][j-1]+1,此方程是在s1[i]和s2[j]匹配的情況下才成立的 即s1[i]==s2[j];
而題目程式碼中給出的判斷條件是if(s1[i-1]==s2[j-1]),這是因為對於一個字串s1來說,它的子串必定"含於"s1[0]..s1[len1-1],而a陣列的下標是從1開始的,這樣做的好處是不需要進行陣列邊界處理
if(s1[i]==s2[j]) {
if(i==0||j==0) a[i][j]=1;
else a[i][j]=a[i-1][j-1]+1;
}
此外,我們對於動態規劃求最優解應該有一個概念:最優解不一定要在狀態中表示出來。例如在這裡,我們只需要把所有子串匹配長度求出來,然後去更新最大長度就可以了。這裡的狀態並不是當前情況下的最優解。
【答案】a[i-1][j-1]+1