题目:http://poj.org/problem?id=2817
题意:
给出n(n<=10)个字符串,每个字符串的长度L小于10,开头可以加上空格,使相邻字符串匹配的最大值为多少?!
解法:
分别求出没两个字符串间的最大匹配数f[i][j];然后求出分别以 dp[i][j] 以 i 为结束字符串, 集合 j 的最大匹配数!!
那么 max(dp[i][p[n]-1]) 即为要求最大值!!
状态转移方程为: dp[i][k]=max(dp[i][k],dp[j][k^p[i-1]]+f[i][j]);
代码:
#include<iostream> #include<cstdio> #include<memory.h> #include<algorithm> using namespace std; const int maxn=12; const int maxm=2050; int p[]={1,2,4,8,16,32,64,128,256,512,1024,2048},n; int dp[maxn][maxm],f[maxn][maxn]; char s[maxn][maxn]; void LCE(int x,int y) { int i,j,l1,l2; l1=strlen(s[x]); l2=strlen(s[y]); for(i=0;i<l1;i++) { for(j=0;j<l2;j++) { int num=0,sum=0; while(num+i<l1&&num+j<l2) { if(s[x][num+i]==s[y][num+j]) sum++; num++; } if(sum>f[x][y]) f[x][y]=sum; } } f[y][x]=f[x][y]; } int main() { int i,j,k,ans; while(scanf("%d",&n),n) { memset(dp,0,sizeof(dp)); memset(f,0,sizeof(f)); for(i=1;i<=n;i++) { scanf("%s",&s[i]); } for(i=1;i<=n;i++) { for(j=1;j<i;j++) { LCE(i,j); } } //cout<<"i k dp:"<<endl; for(k=0;k<p[n];k++) { for(i=1;i<=n;i++) { if(k&p[i-1]) for(j=1;j<=n;j++) { if(k&p[j-1]) dp[i][k]=max(dp[i][k],dp[j][k^p[i-1]]+f[i][j]); } } } for(ans=0,i=1;i<=n;i++)ans=max(ans,dp[i][p[n]-1]); printf("%d\n",ans); } return 0; } /* 5 abc bcd cde aaa bfcde 8 10 abc bc abcd bbc bcd dbc a bacd ebdac ac 19 */