//得到兩個任意長度字符串的公共最長子字符串,這里的子串可以不連續
/*
分析假設,如果串x,y的公共子串z,x.len=m,y.len=n,z.len=l;
如果z[l-1] = x[m-1] = y[n-1],那么z(0...l-2)也是x(0...m-2)和y(0...n-2)的最長子串
如果z[l-1] = x[m-1] != y[n-1],那么z(0...l-2)是x(0...m-2)和y(0...n-1)的最長子串
如果z[l-1] != x[m-1] = y[n-1],那么z(0...l-2)是x(0...m-1)和y(0...n-2)的最長子串
可以確定這是一個動態規划的問題,問題可能有多解,后期選擇的時候需要比較大小
用b[i][j]表示當前位置是否為公共點用於指示構造最長序列,其中0代表命中,1代表向上,2代表向左
c[i][j]表示當前的最大公共長度
*/
#include <iostream> //#include <string> using namespace std; class solution { public: int max_sub_string(string& x,string& y) { int i,j; int m = x.size()+1; int n = y.size()+1; int** b = new int*[m-1]; int** c = new int*[m]; for(i=0;i<m;i++) c[i] = new int[n]; for(i=0;i<m-1;i++) b[i] = new int[n-1]; //initialize for( i=1;i<m;i++) c[i][0] = 0; for( j=0;j<n;j++) c[0][j] = 0; for(i=1;i<m;i++) for(j=1;j<n;j++) { if(x[i-1] == y[j-1]) { c[i][j] = c[i-1][j-1] + 1; b[i-1][j-1] = 0; } else if(c[i-1][j] >= c[i][j-1]) { c[i][j] = c[i-1][j]; b[i-1][j-1] = 1; } else { c[i][j] = c[i][j-1]; b[i-1][j-1] = 2; } } print_route(b,x.size()-1,y.size()-1,x); return c[m-1][n-1]; } void print_route(int** b,int row,int col,string& x) { if(row==-1||col==-1) { return; } if(b[row][col]==0) { print_route(b,row-1,col-1,x); cout<<x[row]; } if(b[row][col]==1) print_route(b,row-1,col,x); if(b[row][col]==2) print_route(b,row,col-1,x); return; } }; int main() { string a,b; solution s; while(cin>>a>>b) cout<<s.max_sub_string(a,b)<<endl; return 0; }