题解
- 题目大意:给你n个字符串,求它们的最长公共子序列
- 显然可以用dp做
- 我们每次可以两两找最长公共子序列,新建一个字符串s[0]来储存
- 那么就可以直接找s[0]与s[i]的最长公共子序列
- 然后我们发现有个问题,就是在找到最长公共子序列的长度时,如果往回找到最长公共子序列
- 考虑记录转移状态:
- ①x[i]==y[i],f[i][j]=f[i-1][j-1]+1
- ②x[i]!=y[i] 且 f[i-1][j]>f[i][j-1] ,f[i][j]=f[i-1][j]
- ③x[i]!=y[i] 且 f[i-1][j]<f[i][j-1], f[i][j]=f[i][j-1]
代码
1 #include <cstdio>
2 #include <iostream>
3 #include <algorithm>
4 #include <cstring>
5 using namespace std;
6 int len[110][110],step[110][110],t,m;
7 char s[110][110];
8 void dp(char s1[110],char s2[110])
9 {
10 memset(len,0,sizeof(len));
11 memset(step,0,sizeof(step));
12 int len1=strlen(s1),len2=strlen(s2);
13 for (int i=1;i<=len1;i++)
14 for (int j=1;j<=len2;j++)
15 {
16 if (s1[i-1]==s2[j-1])
17 {
18 len[i][j]=len[i-1][j-1]+1;
19 step[i][j]=0;
20 }
21 else
22 if (len[i-1][j]>=len[i][j-1])
23 {
24 len[i][j]=len[i-1][j];
25 step[i][j]=1;
26 }
27 else
28 {
29 len[i][j]=len[i][j-1];
30 step[i][j]=2;
31 }
32 }
33 int a=len1,b=len2,w=len[len1][len2]-1;
34 char s3[110]={};
35 for (int i=1;i<=len[len1][len2];i++)
36 {
37 while (s1[a-1]!=s2[b-1])
38 {
39 if (step[a][b]==0) a--,b--;
40 else
41 if (step[a][b]==1) a--;
42 else b--;
43 }
44 s3[w]=s1[a-1]; w--;
45 if (step[a][b]==0) a--,b--;
46 else
47 if (step[a][b]==1) a--;
48 else b--;
49 }
50 strcpy(s[0],s3);
51 m=len[len1][len2];
52 }
53 int main()
54 {
55 scanf("%d",&t);
56 for (int k=1;k<=t;k++)
57 {
58 int n,o=0;
59 scanf("%d",&n);
60 for (int i=0;i<=n-1;i++) scanf("%s",s[i]);
61 for (int i=1;i<=n-1;i++)
62 {
63 dp(s[0],s[i]);
64 if (m==0&&o!=1)
65 {
66 o=1;
67 printf("0
");
68 }
69 }
70 if (o==0) printf("%d
",m);
71 }
72 }