题意描述:
东东有两个序列A和B。他想要知道序列A的LIS和序列AB的LCS的长度。
注意,LIS为严格递增的,即a1<a2<…<ak(ai<=1,000,000,000)。
Input
第一行两个数n,m(1<=n<=5,000,1<=m<=5,000)
第二行n个数,表示序列A
第三行m个数,表示序列B
Output
输出一行数据ans1和ans2,分别代表序列A的LIS和序列AB的LCS的长度
思路:
LIS:定义状态fi表示以ai结尾的最长上升序列的结果;则有f1 = 1;状态转移:fi = max{fj|j < i ^ Aj < Ai} + 1。最后挑出最大者即可。
LCS:定义状态f[i][j]表示A1,A2…Ai和B1,B2…Bj的LCS长度;则有初始时f[1][0]=f[0][1]=f[0][0]=0;当Ai == Bj时,f[i][j] = f[i-1][j-1] + 1,否则f[i][j] = max(f[i-1][j],f[i][j-1])。最后答案为f[n][n]。
代码:
1 #include<iostream> 2 #include<algorithm> 3 4 using namespace std; 5 int m,n; 6 const int maxn = 5010; 7 long a[maxn],b[maxn]; 8 9 int lis[maxn],lcs[maxn][maxn]; 10 int res_lis,res_lcs,temp; 11 12 int main() 13 { 14 ios::sync_with_stdio(false); 15 cin>>n>>m; 16 for(int i=1;i<=n;++i) 17 cin >> a[i]; 18 for(int j=1;j<=m;++j) 19 cin >> b[j]; 20 21 lis[1] = 1; 22 res_lis = res_lcs = 0; 23 for(int i=1;i<=n;++i) 24 { 25 temp = 0; 26 for(int j=1;j<i;++j) 27 if(a[j] < a[i])temp=max(temp,lis[j]); 28 lis[i]=temp+1; 29 res_lis=max(res_lis,lis[i]); 30 } 31 32 lcs[1][0]=lcs[0][1]=lcs[0][0]=0; 33 for(int i=1;i<=n;++i) 34 for(int j=1;j<=m;++j) 35 { 36 if(a[i] == b[j]) 37 lcs[i][j] = lcs[i-1][j-1] + 1; 38 else lcs[i][j] = max(lcs[i-1][j],lcs[i][j-1]); 39 } 40 cout<<res_lis<<" "<<lcs[n][m]; 41 return 0; 42 }