HDU 4681 string 求最长公共子序列的简单DP+暴力枚举
先预处理,用求最长公共子序列的DP顺着处理一遍,再逆着处理一遍。
再预处理串a和b中包含串c的子序列,当然,为了使这子序列尽可能短,会以c 串的第一个字符开始 ,c 串的最后一个字符结束
将这些起始位置先记录下来,然后枚举这些位置,最大的值输出,看一下代码,你就会顿悟了····哈哈。
贴代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define N 1005 5 using namespace std; 6 char a[2][N],b[N];//a[0]为串a,a[1]为串b,b为串c 7 int dp1[N][N],dp2[N][N]; 8 int len[3],num[2];//len[2]为串c的长度 9 struct node 10 { 11 int s,e; 12 } p[2][N]; 13 void init()//dp顺序,逆序求一次最长公共子序列 14 { 15 for(int i=0; i<=len[1]+1; ++i) 16 { 17 dp1[0][i] = 0; 18 dp2[len[0]+1][i]=0; 19 } 20 for(int i=0; i<=len[0]+1; ++i) 21 { 22 dp1[i][0] = 0; 23 dp2[i][len[1]+1] =0; 24 } 25 for(int i=1; i<=len[0]; ++i) 26 { 27 for(int j=1; j<=len[1]; ++j) 28 { 29 if(a[0][i] == a[1][j] ) dp1[i][j] = dp1[i-1][j-1]+1; 30 else dp1[i][j] = max(dp1[i-1][j],dp1[i][j-1]); 31 } 32 } 33 for(int i=len[0]; i>=1; --i) 34 { 35 for(int j=len[1]; j>=1; --j) 36 { 37 if(a[0][i]==a[1][j]) dp2[i][j]=dp2[i+1][j+1]+1; 38 else dp2[i][j] = max(dp2[i+1][j],dp2[i][j+1]); 39 } 40 } 41 } 42 //从串中找一个包含c串的以c[0]为开始,以c[len-1]为结束的一段,记录下起始位置 43 int pipei(int ind,int start) 44 { 45 int i,j=1; 46 for(i=start+1; i<=len[ind]; ++i) 47 { 48 if(a[ind][i] == b[j]) ++j; 49 if(j==len[2]) break; 50 } 51 if(j <len[2]) return -1; 52 else return i; 53 } 54 //预处理出a串和b串中所有如上所述的子串的起始位置 55 void yumeiju(int ind) 56 { 57 num[ind] = 0; 58 for(int i=1; i<=len[ind]; ++i) 59 { 60 if(a[ind][i] == b[0]) 61 { 62 int e = pipei(ind,i); 63 if(e == -1) continue; 64 p[ind][num[ind]].s=i; 65 p[ind][num[ind]].e = e; 66 ++num[ind]; 67 } 68 } 69 } 70 //枚举所有的可能,求解 71 int meiju() 72 { 73 init(); 74 yumeiju(0); 75 yumeiju(1); 76 int ans=0; 77 for(int i=0; i<num[0]; ++i) 78 { 79 for(int j=0; j<num[1]; ++j) 80 { 81 if(dp1[p[0][i].s-1][p[1][j].s-1] + dp2[p[0][i].e+1][p[1][j].e+1] > ans) 82 ans = dp1[p[0][i].s-1][p[1][j].s-1] + dp2[p[0][i].e+1][p[1][j].e+1] ; 83 } 84 } 85 return ans +len[2]; 86 } 87 int main() 88 { 89 // freopen("in.txt","r",stdin); 90 int t; 91 scanf("%d",&t); 92 a[0][0]='#'; 93 a[1][0] ='#'; 94 for(int ser =1; ser<=t; ++ser) 95 { 96 scanf("%s%s%s",a[0]+1,a[1]+1,b); 97 len[0]= strlen(a[0])-1; 98 len[1] = strlen(a[1])-1; 99 len[2] = strlen(b); 100 printf("Case #%d: %d\n",ser,meiju()); 101 } 102 return 0; 103 }