给定两个字符串,求解两个字符串的最长子序列(不是最长子串)
如果采用暴力解法的话,对于两个长分别为 m、n 的字符串来说,各有 2^ n 个子串
如果需要两两比较的话,会有 2^(m + n) 次比较,每一次比较中又会有很多的工作量,
所以,不可取
采用DP的方法:
对于两个串
*****a
*****b
如果 a 和 b 相等,那么就可以将问题转化为求前面的最长子序列然后拼接上最
后的a,如果 a 和 b 不等,那么就可以将其中一个去掉,求剩下两个串的最长
子序列,于是就有状态转移方程:
由于当 m 和 n 属于其余情况的时候,最长子序列的规模一定会比 a[m]== b[n] 的时候小,
所以这里不用二者取最小值
定义一个二维数组,用来保存最长子序列的长度,对于每一个元素,只要按照上面的状态转移
方程,将 T 换成数组的名字即可
代码:这份代码只经过自己编造数据检验,如有不足,请多多指正
intget(int tar[101][101], string a, string b,int m,int n)// 为了适应变化,tar的大小可以动态申请{if(m ==0|| n ==0){return0;}if(tar[m][n]){return tar[m][n];}if(a[m -1]== b[n -1]){
tar[m][n]=get(tar, a, b, m -1, n -1)+1;return tar[m][n];}else{
tar[m][n]=max(get(tar, a, b, m -1, n),get(tar, a, b, m, n -1));return tar[m][n];}}intmain(){
string a, b;
cin >> a >> b;int tar[101][101]={{0}}, m = a.length(), n = b.length(), i;for(i =0; i <= m;++i){
tar[i][0]=0;}for(i =1; i <= n;++i){
tar[0][i]=0;}get(tar, a, b, m, n);
cout << tar[m][n];return0;}
迭代:
intget(string text1, string text2){int** a, i, m = text1.length(), n = text2.length();
a =newint*[m +1];for(i =0; i <= m;++i){
a[i]=newint[n +1];
a[i][0]=0;}for(int j =0; j <= n;++j){
a[0][j]=0;}for(i =1; i <= m;++i){for(int j =1; j <= n;++j){if(text1[i -1]== text2[j -1]){
a[i][j]= a[i -1][j -1]+1;}else{
a[i][j]=max(a[i -1][j], a[i][j -1]);}}}return a[m][n];}