题意描述:
东东有两个序列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 }