您的位置:首页 > 产品设计 > UI/UE

CF 346B. Lucky Common Subsequence(DP+KMP)

2013-09-25 10:06 246 查看
这题确实很棒。。又是无想法。。其实是AC自动机+DP的感觉,但是只有一个串,用kmp就行了。

dp[i][j][k],k代表前缀为virus[k]的状态,len表示其他所有状态串,处理出Ac[len][26]数组来,DP就可以了。状态转移那里一直没想清楚,wa了很多次,记录路径倒是不复杂,瞎搞搞就行。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
char s1[103],s2[103],virus[103];
int dp[103][103][103];
int pre[103][103][103];
int pre1[103][103][103];
int Ac[111][31];
int next[103];
char ans[111];
void kmp()
{
int i,j,len,temp;
len = strlen(virus);
next[0] = -1;
j = -1;
for(i = 1; i < len; i ++)
{
while(j >= 0&&virus[j+1] != virus[i])
j = next[j];
if(virus[j+1] == virus[i]) j ++;
next[i] = j;
}
for(i = 0; i < len; i ++)
{
for(j = 0; j < 26; j ++)
{
temp = i;
while(temp >= 0&&virus[temp+1] != 'A'+j)
temp = next[temp];
if(virus[temp+1] == 'A' + j) temp ++;
if(temp == -1)
Ac[i][j] = len;
else
Ac[i][j] = temp;
}
}
for(i = 0; i < 26; i ++)
{
if(i + 'A' == virus[0])
Ac[len][i] = 0;
else
Ac[len][i] = len;
}
}
int main()
{
int i,j,k,len1,len2,len,maxz,a,b,kk;
scanf("%s%s%s",s1,s2,virus);
len1 = strlen(s1);
len2 = strlen(s2);
len = strlen(virus);
kmp();
for(i = 1; i <= len1; i ++)
{
for(j = 1; j <= len2; j ++)
{
for(k = 0; k <= len; k ++)
{
if(k == len-1) continue;
if(dp[i][j][k] < dp[i-1][j][k])
{
dp[i][j][k] = dp[i-1][j][k];
pre[i][j][k] = 2;
pre1[i][j][k] = k;
}
if(dp[i][j][k] < dp[i][j-1][k])
{
dp[i][j][k] = dp[i][j-1][k];
pre[i][j][k] = 3;
pre1[i][j][k] = k;
}
if(s1[i-1] == s2[j-1])
{
if(Ac[k][s1[i-1]-'A'] == len-1) continue;
else if(dp[i][j][Ac[k][s1[i-1]-'A']] < dp[i-1][j-1][k] + 1)
{
dp[i][j][Ac[k][s1[i-1]-'A']] = dp[i-1][j-1][k] + 1;
pre[i][j][Ac[k][s1[i-1]-'A']] = 1;
pre1[i][j][Ac[k][s1[i-1]-'A']] = k;
}
}
}
}
}
maxz = 0;
for(i = 1; i <= len1; i ++)
{
for(j = 1; j <= len2; j ++)
{
for(k = 0; k <= len; k ++)
{
if(maxz < dp[i][j][k])
{
maxz = dp[i][j][k];
a = i;
b = j;
kk = k;
}
}
}
}
if(maxz == 0)
{
printf("0\n");
return 0;
}
int num = 0;
//printf("%d\n",maxz);
while(a != 0&&b != 0)
{
if(pre[a][b][kk] == 1)
{
ans[num++] = s1[a-1];
kk = pre1[a][b][kk];
a --;
b --;
}
else if(pre[a][b][kk] == 2)
{
kk = pre1[a][b][kk];
a --;
}
else if(pre[a][b][kk] == 3)
{
kk = pre1[a][b][kk];
b --;
}
else
break;
}
for(i = num-1; i >= 0; i --)
{
printf("%c",ans[i]);
}
printf("\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: