码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round#201(div1) D. Lucky Common Subsequence

时间:2014-09-09 20:03:59      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   ar   for   art   

题意:给定两个串,求出两个串的最长公共子序列,要求该公共子序列不包含virus串。

用dp+kmp实现

dp[i][j][k]表示以i结尾的字符串和以j结尾的字符串的公共子序列的长度(其中k表示该公共子序列的与virus的匹配程度)很显然,当k==strlen(virus)时,该公共子序列不是我们所求得

 当添加一个字符时,如果失配,这时不能让k直接等于0,而是要用kmp给k一个合理的值。

bubuko.com,布布扣
  1 #include <stdio.h>
  2 #include <string.h>
  3 const int N = 100 + 10;
  4 int dp[N][N][N];
  5 int pre[N][N][N][3];
  6 char s1[N],s2[N],vir[N];
  7 int next[N];
  8 char ans[N];
  9 void makeNext(int n)
 10 {
 11     next[0] = -1;
 12     int i = 0,j=-1;
 13     while(i < n)
 14     {
 15         if(j==-1 || vir[i] == vir[j])
 16         {
 17             i++;
 18             j++;
 19             next[i] = j;
 20         }
 21         else
 22             j = next[j];
 23     }
 24 }
 25 void DP(int x, int y, int z, int x1, int y1, int z1, int val)
 26 {
 27     if(dp[x][y][z] < dp[x1][y1][z1] + val)
 28     {
 29         dp[x][y][z] = dp[x1][y1][z1] + val;//状态转移
 30         //保存路径
 31         pre[x][y][z][0] = x1;
 32         pre[x][y][z][1] = y1;
 33         pre[x][y][z][2] = z1;
 34     }
 35 }
 36 int main()
 37 {
 38     int i,j,k;
 39     scanf("%s%s%s",s1+1,s2+1,vir);
 40     int len1 = strlen(s1+1);
 41     int len2 = strlen(s2+1);
 42     int len3 = strlen(vir);
 43     memset(dp,0,sizeof(dp));
 44     memset(pre,-1,sizeof(pre));
 45     makeNext(len3);
 46     for(i=1; i<=len1; ++i)
 47         for(j=1; j<=len2; ++j)
 48         {
 49             for(k=0; k<len3; ++k)
 50             {
 51                 DP(i,j,k,i-1,j,k,0);//s1[i] != s2[j]时的转移
 52                 DP(i,j,k,i,j-1,k,0);
 53                 if(s1[i] == s2[j])//s1[i] == s2[j]
 54                 {
 55                     if(s1[i] == vir[k])
 56                     {
 57                         DP(i,j,k+1,i-1,j-1,k,1);
 58                     }
 59                     else
 60                     {
 61                         int p = next[k];
 62                         while(p!=-1 && s1[i] != vir[p]) p = next[p];
 63                         if(p==-1)
 64                             p = 0;
 65                         if(s1[i] == vir[p])
 66                             DP(i,j,p+1,i-1,j-1,k,1);
 67                         else
 68                             DP(i,j,p,i-1,j-1,k,1);
 69                     }   
 70                 }
 71             }
 72         }
 73     int z;
 74     int Max = -1;
 75     for(k=0; k<len3; ++k)
 76         if(Max < dp[len1][len2][k])
 77         {
 78             Max = dp[len1][len2][k];
 79             z = k;
 80         }   
 81     if(Max <= 0)
 82         printf("0\n");
 83     else//根据路径求出最长公共子序列
 84     {
 85         int tMax = Max;
 86         int x = len1,y = len2;
 87         while(pre[x][y][z][0] != -1)
 88         {
 89             int xx = pre[x][y][z][0];
 90             int yy = pre[x][y][z][1];
 91             int zz = pre[x][y][z][2];
 92             if(x-xx==1 && y-yy==1&&s1[x] == s2[y]) 
 93                 ans[Max--] = s1[x];
 94             x = xx;y=yy;z=zz;
 95         }
 96         for(i=1; i<=tMax; ++i)
 97             printf("%c",ans[i]);
 98         printf("\n");
 99     }
100 }
View Code

 

Codeforces Round#201(div1) D. Lucky Common Subsequence

标签:style   blog   http   color   os   io   ar   for   art   

原文地址:http://www.cnblogs.com/justPassBy/p/3963200.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!