問題描述
給定兩個字串,尋找這兩個字串之間的最長公共子串行。
輸入格式
輸入兩行,分別包含乙個字串,僅含有小寫字母。
輸出格式
最長公共子串行的長度。
樣例輸入
abcdgh
aedfhb
樣例輸出
3樣例說明
最長公共子串行為a,d,h。
資料規模和約定
字串長度1~1000。
分析:求最長公共子串行,用動態規劃~只需建立乙個長寬為兩個字串長度+1的二維陣列~dp[i][j]表示string a的前i個字元構成的字串和string b的前j個字元構成的字串這兩者得到的最長公共子串行的長度為dp[i][j]~~~所以第0行和第0列所有的數都為0~
根據遞推公式:
最後乙個格仔的長度就是兩個字串的最長公共子串行的長度~
#include using namespace std;
int dp[1001][1001];
int main()
} cout << dp[a.length()][b.length()];
return 0;
}
這個解法只能解決求最長子序列長度的問題,並不能得到最長子序列。因此,可以改良一下:
一、問題描述
求兩個字串行的公共最長子序列。例如字串行abcbdb和字串行acbbabdbb的最長公共子串行為acbdb。
二、問題分析
(1)用l[i][j]表示子串行xi和yj的最長公共子串行的長度
,動態規劃函式為
l[i][j] = l[i - 1][j - 1] + 1, xi等於yj
= max(l[i][j - 1], l[i - 1][j]
), xi不等於yj
邊界條件第0行和第0列均為0,即l[i][0] = l[0][j] = 0
上例中l填寫情況如下
(2)因為不只要求出最大長度,還要尋找到公共最長子序列
,所以在填表l[i][j]過程中,再填乙個表s[i][j],
若xi等於yj,設定s[i][j] = 1;
若xi不等於yj,並且len[i + 1][j] >= len[i][j + 1],設定s[i][j] = 2; 若
xi不等於yj,並且
len[i + 1][j] < len[i][j + 1],設定
s[i][j] = 3;
填表s[i][j]完成後,具體如何找到最長公共子串行詳見**注釋。
上例中s填寫情況及尋找最長公共子串行過程如下
三、演算法**
public static void maxcommonchar(char a, char b)else if(len[i + 1][j] >= len[i][j + 1])else
} }
int k = len[m][n]; //最長公共子串長度
char commonchars = new char[k];//儲存最長公共子串
int i = m, j = n; //從右下角的格仔出發
for(;i > 0 && j > 0;)else if(flags[i][j] == 2)else
} system.out.println("最長公共子串行長度為:" + len[m][n]);
system.out.print("最長公共子串行為:");
for(int l = 0; l <= len[m][n] - 1; l++)
}
最長公共子串行問題(動態規劃演算法)
問題 給出兩個字串a a1 a2a3 an和b b1 b2b3 bm,求a和b的最長公共子串行的長度。例如 a xyxxzxyzxy,b zxzyyzxxyxxz,則它們的最長公共子串行為xy z,長度為6。注意 最長公共子串行不一定要求連續的字串,只講究先後順序一致。約定 l i,j 表示這樣兩個...
動態規劃之最長公共子串行演算法
動態規劃之最長公共子串行演算法 演算法思想 假設x x1,x2,xm y static void init xy void getchar for i 1 i n i getchar static void lcs length void else if c i 1 j c i j 1 else p...
動態規劃之最長公共子串行
最長公共子串行簡介 舉例說明並分析 塊測試結果 乙個給定序列的子串行是在該序列中刪去若干元素後得到的序列,確切的說,若給定序列x 則另一串行z x的子串行是指存在乙個嚴格的下標序列,使得對於所有的j 0,1,k 1有zj xij。例如序列z 是序列x 的子串行,相應的遞增下標序列維。最長公共子串行問...