#include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; #define maxn 1111 char a[maxn],b[maxn],c[maxn]; int dp1[maxn][maxn],dp2[maxn][maxn],n,m,len; struct node//记录在字符串a,b中,c串的首尾位置 { int x,y; }; void lcs()//求最长公共子序列长 { int i, j,k; //从字符串左到右 for(i=0;i<n;i++) for(j=0;j<m;j++) if(a[i]==b[j]) dp1[i+1][j+1]=dp1[i][j]+1; else dp1[i+1][j+1]=max(dp1[i][j+1],dp1[i+1][j]); //从字符串右到左 for(i=n-1;i>=0;i--) for(j=m-1;j>=0;j--) if(a[i]==b[j]) dp2[i+1][j+1]=dp2[i+2][j+2]+1; else dp2[i+1][j+1]=max(dp2[i+1][j+2],dp2[i+2][j+1]); } void find(char str[],int n,int &t,node e[])//找到c串在a,b中的首尾位置 { int i,j,k; for(i=0;i<n;i++) { if(str[i]==c[0]) { for(j=i+1,k=1;j<n;j++) { if(str[j]==c[k])k++; if(k==len)break; } if(k==len){e[t].x=i+1;e[t++].y=j+1;} else break; } } } int main() { int T,tt=0; scanf("%d",&T); while(T--) { memset(dp1,0,sizeof(dp1)); memset(dp2,0,sizeof(dp2)); int i,j,k; scanf("%s%s%s",a,b,c); n=strlen(a); m=strlen(b); len=strlen(c); lcs(); int ans,num1,num2; node e[maxn],f[maxn]; ans=num1=num2=0; find(a,n,num1,e); find(b,m,num2,f); for(i=0;i<num1;i++) for(j=0;j<num2;j++) ans=max(ans,dp1[e[i].x-1][f[j].x-1]+dp2[e[i].y+1][f[j].y+1]); printf("Case #%d: %d ",++tt,ans+len); } return 0; } /* 先求出a,b的最长公共子序列,从开头和末尾开始的都要 其中dp1[i][j]表示a中第i个字符之前,b中第j个字符之前的最长公共子序列长 dp2[i][j]表示a中第i个字符之后,b中第j个字符之后的最长公共子序列长 用find找到a中所有c首尾所在位置,在首位置固定的情况下找到末位置最小的即可,因为更长的会使结果值较小,存在结构体重 同理找到b的 e[i].x,e[i].y,f[j].x,f[j].y 那么d最长为ans=max(ans,dp1[e[i].x-1][f[j].x-1]+dp2[e[i].y+1][f[j].y+1]+len), 就是说包含c的部分已经固定,只要加上之前和之后的最长公共子序列长就好了 */