1 /*
2 首先,dp的最开始是定义状态 dp[i][j] 表示A串的前i个,与B串的前j个,并以B[j]为结尾的LCIS 的长度.
3 状态转移方程:
4 if(A[i]==B[j]) dp[i][j]=max(dp[i-1][k])+1; ( 1 <= k < j )
5 else dp[i][j]=dp[i-1][j];
6 然后选择循环顺序,就可以将算法的复杂度降为n*n.
7 转自:http://www.cnblogs.com/chenhuan001/archive/2013/03/26/2982677.html
8 PS:用一维数组来记录路径老是wa,测了好多组都是对的,从昨晚一直纠结到现在,先mark,以后看,真想砸电脑*/
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <iostream>
13 using namespace std;
14 #define N 550
15 struct node
16 {
17 int x,y;
18 }path[N][N];
19 int dp[N][N];
20 int s[N],t[N];
21
22 int main()
23 {
24 int t1;
25 while(scanf("%d",&t1)!=EOF)
26 {
27 while(t1--)
28 {
29 memset(path,0,sizeof(path));
30 int n,m;
31 scanf("%d",&n);
32 for(int i=1;i<=n;i++)
33 scanf("%d",&s[i]);
34 scanf("%d",&m);
35 for(int i=1;i<=m;i++)
36 scanf("%d",&t[i]);
37 memset(dp,0,sizeof(dp));
38 int mx=0;
39 for(int i=1;i<=n;i++)
40 {
41 mx=0;
42 int tx=0,ty=0;
43 for(int j=1;j<=m;j++)
44 {
45 dp[i][j] = dp[i-1][j];
46 path[i][j].x=i-1;
47 path[i][j].y=j;
48 if( s[i]>t[j] && mx<dp[i-1][j])
49 {
50 mx=dp[i-1][j];
51 tx=i-1;//修改最长匹配的下标
52 ty=j;//修改最长匹配的下标
53 }
54 if( s[i] == t[j] )
55 {
56 dp[i][j]=mx+1;
57 path[i][j].x=tx;//记录前一个匹配的下标
58 path[i][j].y=ty;//记录前一个匹配的下标
59 }
60 }
61 }
62 mx=-1;
63 int id;
64 for(int i=1;i<=m;i++)
65 if(dp[n][i]>mx)
66 {
67 mx=dp[n][i];
68 id=i;
69 }
70 int save[N];
71 int cnt=0;
72 int tx,ty;
73 tx=n; ty=id;
74 while( dp[tx][ty] != 0 )
75 {
76 int tmpx,tmpy;
77 tmpx=path[tx][ty].x;
78 tmpy=path[tx][ty].y;
79 if(dp[tx][ty]!=dp[tmpx][tmpy])
80 {
81 save[cnt++]=t[ty];
82 }
83 tx=tmpx; ty=tmpy;
84 }
85 printf("%d\n",mx);
86 for(int i=cnt-1;i>=0;i--)
87 printf("%d ",save[i]);
88 printf("\n");
89 }
90 }
91 return 0;
92 }