您的位置:首页 > 其它

GDKOI2003 最大公共子串

2012-03-28 22:47 337 查看
AOJ链接:最大公共子串

这道题求多个字符串的最大公共序列(非连续)的长度,题目中说明了所有串的乘积不超过30000;

题解将状态记录在一个长度为30000的数组中,使用类似编码的方式(我的理解)进行存取;

和算法导论上对LCS的解法不大一样(递归而不是递推,计算量会少一些),仍然是动态规划的思想;

0MS,学习了。

下面的代码是看懂了书上的后,自己写的;

起先觉得第47、48行的恢复多余,后来发现并不是:包含回溯的过程,需要恢复原来的下标。

# include <stdio.h>
# include <string.h>

char str[102][102];
int c[30005];
int tmp[102];
int len[102];

int get(int n, int *x);

int main()
{
int T, N, i;

scanf("%d", &T);
while (T--)
{
scanf("%d", &N);
memset(c, 0xff, sizeof(c));
for (i = 1; i <= N; ++i)
{
scanf("%s", str[i]);
tmp[i] = len[i] = (int)strlen(str[i]);
}
printf("%d\n", get(N, tmp));
}

return 0;
}

int get(int n, int *x)
{
int i, j, index, ret, rem;

for (i = 1; i <= n; ++i)
if (x[i] == 0) return 0;
for (i = n-1, index = x
-1; i >= 1; --i)
index = index*len[i] + x[i]-1;
if (c[index] >= 0) return c[index];
for (i = 2; i <= n; ++i)
if (str[1][x[1]-1] != str[i][x[i]-1]) break;
if (i > n)
{
for (j = 1; j <= n; ++j)
--x[j];
ret = get(n, x) + 1;
for (j = 1; j <= n; ++j)
++x[j];
} else
{
ret = 0;
for (j = 1; j <= n; ++j)
{
--x[j];
rem = get(n, x);
if (rem > ret) ret = rem;
++x[j];
}
}
c[index] = ret;
return ret;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐