~~和其他不同的是,本题目是找大于等于2个数组的最长公共子序列
废话少说,上题:
从一个给定的串中删去(不一定连续地删去)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 <stdlib.h>
#include <string.h>
char a[110][110];//二维字符数组保存字符
int d[30010];
int len[110];//一维len保存每个字符数组的长度
int n;
int f(int l[])
{
int i, j, index, ret, t;
for (i = 1; i <= n; i++)
if (l[i] == 0)//判断字符长的是否为0,为0直接以0退出
return 0;
//-------------------------------------------------------------
for (index = l[n] - 1, i = n - 1; i >= 1; i--)
index = index * len[i] + l[i] - 1;//转化为一维数组,原理有待考究(对我来说)
if (d[index] >= 0)
return d[index];//一但有值,直接返回
//-------------------------------------------------------------
for (i = 2; i <= n; i++)
if (a[1][l[1] - 1] != a[i][l[i] - 1])
break;//在看每个字符串的末尾(我当时看错了,,以为是倒数第二)
if (i > n)//字符串末尾全相同
{
for (j = 1; j <= n; j++)
l[j]--;
ret = f(l) + 1;
for (j = 1; j <= n; j++)
l[j]++;//记得恢复
}
else//有不同,递归
{
ret = 0;
for (j = 1; j <= n; j++)
{
l[j]--;//感觉类似于dfs,历遍了
t = f(l);
if (t > ret)
ret = t;
l[j]++;
}
}
d[index] = ret;
return ret;
}
//-------------------------------------------------------------
int main()
{
int T, i;
int l[110];//保存多维字符数组长度的动态变化
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
scanf("%s", a[i]);
len[i] = strlen(a[i]);
l[i] = strlen(a[i]);
}
memset(d, -1, sizeof(d));
printf("%d\n", f(l));
}
return 0;
}
这道题横跨我三天,耗时六节课,感觉好难(我菜了)。。。。。。。。。。
参考@猫猫敲给力,感谢学长!!