从一个给定的串中删去(不一定连续地删去)0个或0个以上的字符,剩下地字符按原来顺序组成的串。例如:“ ”,“a”,“xb”,“aaa”,“bbb”,“xabb”,“xaaabbb”都是串“xaaabbb”的子序列。(例子中的串不包含引号。)
编程求N个非空串的最长公共子序列的长度。限制:2<=N<=100;N个串中的字符只会是数字0,1,…,9或小写英文字母a,b,…,z;每个串非空且最多含100个字符;N个串的长度的乘积不会超过30000。
输入格式:
文件第1行是一个整数T,表示测试数据的个数(1<=T<=10)。接下来有T组测试数据。各组测试数据的第1行是一个整数Ni,表示第i组数据中串的个数。各组测试数据的第2到N+1行中,每行一个串,串中不会有空格,但行首和行末可能有空格,这些空格当然不算作串的一部分。
输出格式:
输出T行,每行一个数,第i行的数表示第i组测试数据中Ni个非空串的最长公共子序列的长度。
输入样例:
1
3
ab
bc
cd
输出样例:
0
参考代码:
#include <stdio.h>
#include <string.h>
int n, len[110], dp[30010];
int t, m[100];
char s[110][110];
int max(int a, int b)
{
return a > b ? a : b;
}
int LCS(int array[])
{
int a, b, i, j;
for (i = 1; i <= n; i++)
{
if (array[i] == 0)
return 0;
}
for (a = array[n] - 1, i = n - 1; i >= 1; i--)
a = a * len[i] + array[i] - 1;
if (dp[a] >= 0)
return dp[a];
for (i = 2; i <= n; i++)
if (s[1][array[1] - 1] != s[i][array[i] - 1])
break;
if (i > n)
{
for (j = 1; j <= n; j++)
array[j]--;
b = LCS(array) + 1;
for (j = 1; j <= n; j++)
array[j]++;
}
else
{
b = 0;
for (j = 1; j <= n; j++)
{
array[j]--;
int t = LCS(array);
b = max(b, t);
array[j]++;
}
}
dp[a] = b;
return b;
}
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%s", s[i]);
len[i] = m[i] = strlen(s[i]);
}
memset(dp, -1, sizeof(dp));
printf("%d\n", LCS(m));
}
return 0;
}