HUST 4681 String (DP LCS变形)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4681
题目大意:给定三个字符串A,B,C 求最长的串D,要求(1)D是A的字序列 (2)D是B的子序列 (3)C是D的连续子序列
Sample Input
2
aaaaa
aaaa
aa
abcdef
acebdf
cf
Sample Output
Case #1: 4
Case #2: 3
Hint
For test one, D is "aaaa", and for test two, D is "acf".分析:求A和B的LCS,正反各求一次得到dp1和dp2,然后枚举C在A,B中的起始位置和终止位置,答案为
max { dp1[C在A中起始位置][C在B中起始位置] + dp2[C在A中终止位置][C在D中终止位置]+C的长度 }
代码如下:
1 # include<cstdio> 2 # include<cstring> 3 # include<iostream> 4 using namespace std; 5 # define MAXN 1005 6 char s1[MAXN],s2[MAXN],s3[MAXN]; 7 int dp1[MAXN][MAXN],dp2[MAXN][MAXN];//dp1[][]表示字符串A,B从前往后的最大公共子串,dp2[][]表示字符串A,B从后往前的最大公共子串 8 int len1,len2,len3; 9 int loc11[MAXN],loc12[MAXN],loc21[MAXN],loc22[MAXN];//loc11,loc12表示C在A中起始、终止位置;loc21,loc22表示C在B中起始、终止位置 10 11 int solve(char *str,int len,int loc1[],int loc2[]) 12 { 13 int i,j,k; 14 int cnt =0 ; 15 for(i=1; i<=len; i++) 16 { 17 if(str[i] == s3[1]) 18 { 19 for(j=i,k=1; j<=len&&k<=len3; j++) 20 if(str[j]==s3[k]) 21 k++; 22 if(k != len3+1) 23 break; 24 loc1[cnt] = i; 25 loc2[cnt] = j-1; 26 cnt++; 27 } 28 } 29 return cnt; 30 } 31 int main() 32 { 33 int i,j; 34 int cas,T; 35 scanf("%d",&T); 36 for(cas=1; cas<=T; cas++) 37 { 38 scanf("%s%s%s",s1+1,s2+1,s3+1); 39 len1 = strlen(s1+1); 40 len2 = strlen(s2+1); 41 len3 = strlen(s3+1); 42 43 memset(dp1,0,sizeof(dp1)); 44 for(i=1; i<=len1; i++) 45 for(j=1; j<=len2; j++) 46 { 47 if(s1[i] == s2[j]) 48 dp1[i][j] = dp1[i-1][j-1] + 1; 49 50 else 51 dp1[i][j] = max(dp1[i-1][j], dp1[i][j-1]); 52 } 53 54 55 memset(dp2,0,sizeof(dp2)); 56 for(i=len1; i>=1; i--) 57 for(j=len2; j>=1; j--) 58 { 59 if(s1[i] == s2[j]) 60 dp2[i][j] = dp2[i+1][j+1] + 1; 61 else 62 dp2[i][j] = max(dp2[i+1][j], dp2[i][j+1]); 63 } 64 65 66 int x=solve(s1,len1,loc11,loc12); 67 int y=solve(s2,len2,loc21,loc22); 68 int ans=0; 69 for(i=0; i<x; i++) 70 for(j=0; j<y; j++) 71 ans = max(ans, dp1[loc11[i]-1][loc21[j]-1] + dp2[loc12[i]+1][loc22[j]+1]); 72 printf("Case #%d: %d\n",cas,ans+len3); 73 } 74 return 0; 75 }
把每一件简单的事情做好,就是不简单;把每一件平凡的事情做好,就是不平凡!相信自己,创造奇迹~~