POJ 1699 Best Sequence
我想说只要想错了死都对不了,这是真理~~。
题目大意:
给出n个字符串,要求像下图一样将这些字符串组成一个最短的字符串。
解题思路:
这个题下意识的就应该用KMP来判断前串和后串有几个字母重合啊!!!KMP可是刚学过去的啊!!!为什么要忽略它啊!!
除了计算出任何两个串之间有多少个重合的的字符之外,就是一个DFS了八皇后的思路。
下面是代码:
#include <stdio.h> #include <string.h> int max1,l[15],n; char s[15][25]; int num[15][25]; int map1[12][12]; bool vis[15]; char ans[305]; int judge(int x,int y) { int i=0,j=0; while(i<l[x]) { if(s[x][i]==s[y][j]) { i++; j++; } else { if(j==0)i++; else j=num[x][j]; } if(j==l[y])return -1;//如果串a包含串b 返回-1作为标记 } return j; } void next(int x) { int j=-1; num[x][0]=-1; for(int i=0;i<l[x];i++) { if(j==-1||s[x][i]==s[x][j])num[x][++i]=++j; else j=num[x][j]; } } void dfs(int len,int cnt,int fa) { if(cnt==n) { if(len<max1)max1=len; return ; } for(int i=0;i<n;i++) { if(!vis[i]) { vis[i]=true; if(map1[fa][i]==-1) //如果被包含 后缀还是原来的。 { dfs(len,cnt+1,fa); } else dfs(len+l[i]-map1[fa][i],cnt+1,i); vis[i]=false; } } return ; } int main() { int t,num[15][15]; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%s",s[i]); l[i]=strlen(s[i]); next(i); } for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { map1[i][j]=judge(i,j); //printf("%d ",map1[i][j]); } //puts(""); } max1=100000; memset(vis,false,sizeof(vis)); for(int i=0;i<n;i++) { vis[i]=true; dfs(l[i],1,i); vis[i]=false; } printf("%d\n",max1); } return 0; }