您的位置:首页 > 其它

HDU 4681 String(DP)

2013-08-15 18:28 429 查看
题目链接

枚举A和B中每一段含有C的段,A的前面 后面和B前面后面,求最长公共子序。观察发现,可以预处理最长公共子序。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int dp1[1001][1001],dp2[1001][1001];
char s1[1010];
char s2[1010];
char s3[1010];
char s4[1010];
char s5[1010];
int que1[1010][3];
int que2[1010][3];
int main()
{
int t,cas = 1,i,j,n1,n2,k;
int len1,len2,len3;
scanf("%d",&t);
while(t--)
{
scanf("%s%s%s",s1,s2,s3);
len1 = strlen(s1);
len2 = strlen(s2);
len3 = strlen(s3);
for(i = 0;i <= len1;i ++)
{
for(j = 0;j <= len2;j ++)
{
dp1[i][j] = dp2[i][j] = 0;
}
}
for(i = 1;i <= len1;i ++)
{
for(j = 1;j <= len2;j ++)
{
if(s1[i-1] == s2[j-1])
dp1[i][j] = dp1[i-1][j-1] + 1;
else
dp1[i][j] = max(dp1[i-1][j],dp1[i][j-1]);
}
}
for(i = 0;i < len1;i ++)
{
s4[i] = s1[len1-i-1];
}
for(i = 0;i < len2;i ++)
{
s5[i] = s2[len2-i-1];
}
for(i = 1;i <= len1;i ++)
{
for(j = 1;j <= len2;j ++)
{
if(s4[i-1] == s5[j-1])
dp2[i][j] = dp2[i-1][j-1] + 1;
else
dp2[i][j] = max(dp2[i-1][j],dp2[i][j-1]);
}
}
n1 = n2 = 0;
for(i = 0;i < len1;i ++)
{
if(s1[i] == s3[0])
{
k = 1;
for(j = i+1;j < len1;j ++)
{
if(s1[j] == s3[k])
k ++;
if(k == len3) break;
}
if(j != len1)
{
que1[n1][0] = i;
que1[n1][1] = j;
n1 ++;
}
}
}
for(i = 0;i < len2;i ++)
{
if(s2[i] == s3[0])
{
k = 1;
for(j = i+1;j < len2;j ++)
{
if(s2[j] == s3[k])
k ++;
if(k == len3) break;
}
if(j != len2)
{
que2[n2][0] = i;
que2[n2][1] = j;
n2 ++;
}
}
}
int ans = 0;
/*for(i = 1;i <= len1;i ++)
{
for(j = 1;j <= len2;j ++)
{
printf("%d ",dp1[i][j]);
}
printf("\n");
}*/
/*for(i = 0;i < n1;i ++)
{
printf("%d %d\n",que1[i][0],que1[i][1]);
}
for(i = 0;i < n2;i ++)
{
printf("%d %d\n",que2[i][0],que2[i][1]);
}*/
for(i = 0;i < n1;i ++)
{
for(j = 0;j < n2;j ++)
{
ans = max(ans,dp1[que1[i][0]][que2[j][0]] + dp2[len1-que1[i][1]-1][len2-que2[j][1]-1]);
}
}
printf("Case #%d: %d\n",cas++,ans + len3);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: