2017.10.5 最短母串 思考记录
来源:互联网 发布:北京编程培训学校 编辑:程序博客网 时间:2024/06/09 21:16
这个题n<=15,可以用10表示选取情况下的最优值
预处理两个串之间的连接关系,然后枚举状态转移
然而这个题还要输出方案,,而且还不让你开空间。
所以只能记录前继动态判断、、
所以十分难写难调
码:
#include<iostream>#include<cstdio>#include<cstring>using namespace std;int n,i,j,k,l,lin[15],g1[16385][15],g2[16385][15],er[15],daan2[15],p;long long f[16385][15],lj[16][16],ans=2147483647,len[15];char str[15][60],daan[800],lin3[800];bool wu[15];int main(){ memset(f,0x7f,sizeof(f)); scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%s",str[i]+1); len[i]=strlen(str[i]+1); } for(i=1;i<=n;i++) for(j=1;j<=n;j++) { if(i==j||len[i]>len[j])continue; for(k=1;k<=len[j]-len[i];k++) { for(l=1;l<=len[i];l++) { if(str[i][l]!=str[j][k+l-1])break; } if(l>len[i])wu[i]=1; } } int cnt=0; for(i=1;i<=n;i++) { if(wu[i])continue;++cnt; for(j=1;j<=len[i];j++) str[cnt][j]=str[i][j]; len[cnt]=len[i]; } n=cnt; for(i=1;i<=n;i++)//最长延伸(第一个串) { for(j=1;j<=n;j++) { if(i==j)continue; for(k=1;k<=len[i];k++) { for(l=1;l<=len[j];l++) { if(str[i][k+l-1]!=str[j][l])break; } if(k+l-2==len[i]) { lj[i][j]=len[i]-k+1; break; } } } } er[0]=1; for(i=1;i<=n;i++) er[i]=er[i-1]*2; for(i=1;i<=n;i++) f[er[i-1]][i-1]=len[i],g1[er[i-1]][i-1]=-1; for(i=1;i<er[n];i++)//枚举状态 { for(j=0;j<n;j++)//枚举上一个是啥 { for(k=0;k<n;k++)//枚举这一个放啥 { if(i&er[k])continue; if(f[i|er[k]][k]==f[i][j]+len[k+1]-lj[j+1][k+1]&&f[i|er[k]][k]<=1000000000) { //判断字典序;;;;;//if(f[i|er[]])int lin2=0; int lol1=i,lol2=j; while(lol1!=-1)//拆出前继 ,放到lin里,顺序是反的 { lin[++lin2]=lol2+1;//位置要加1 int tmp=lol1; lol1=g1[lol1][lol2]; lol2=g2[tmp][lol2]; } int lin4=0; lin[lin2+1]=0; for(l=lin2;l>=1;l--)//倒着放字符 { for(p=lj[lin[l+1]][lin[l]]+1;p<=len[lin[l]];p++) { lin3[++lin4]=str[lin[l]][p]; } } for(l=lj[j+1][k+1]+1;l<=len[k+1];l++) { lin3[++lin4]=str[k+1][l]; }// for(int y=1;y<=lin4;y++)cout<<lin3[y];// cout<<endl; lin2=0; lol1=i|er[k],lol2=k; while(lol1!=-1)//拆出前继 ,放到daan2里,顺序是反的 { daan2[++lin2]=lol2+1; int tmp=lol1; lol1=g1[lol1][lol2]; lol2=g2[tmp][lol2]; } //看答案是否字典序 lin4=0; daan2[lin2+1]=0; for(l=lin2;l>=1;l--) { for(p=lj[daan2[l+1]][daan2[l]]+1;p<=len[daan2[l]];p++) { daan[++lin4]=str[daan2[l]][p]; } }// for(int y=1;y<=lin4;y++)cout<<daan[y];// cout<<endl<<endl; bool huan=0; for(l=1;l<=f[i|er[k]][k];l++) { if(lin3[l]<daan[l]){huan=1;break;} if(lin3[l]>daan[l]){break; } } if(huan) { g1[i|er[k]][k]=i; g2[i|er[k]][k]=j; }} if(f[i|er[k]][k]>f[i][j]+len[k+1]-lj[j+1][k+1]) { f[i|er[k]][k]=f[i][j]+len[k+1]-lj[j+1][k+1]; g1[i|er[k]][k]=i; g2[i|er[k]][k]=j; } } } } for(i=0;i<n;i++) ans=min(ans,f[er[n]-1][i]); for(i=1;i<=ans;i++)daan[i]='a'; for(i=0;i<n;i++) { if(f[er[n]-1][i]==ans) { int lin2=n; int lol1=er[n]-1,lol2=i; while(lol1!=-1) { lin[lin2]=lol2+1; int tmp=lol1; lol1=g1[lol1][lol2]; lol2=g2[tmp][lol2]; lin2--; } //看答案是否字典序 int lin4=0; for(j=1;j<=n;j++) { for(k=lj[lin[j-1]][lin[j]]+1;k<=len[lin[j]];k++) { lin3[++lin4]=str[lin[j]][k]; } } bool huan=0; for(j=1;j<=ans;j++) { if(daan[j]>lin3[j]) { huan=1; break; } if(daan[j]<lin3[j]) break; } if(huan)for(k=1;k<=ans;k++) daan[k]=lin3[k]; } } for(i=1;i<=ans;i++) printf("%c",daan[i]);}
阅读全文
0 0
- 2017.10.5 最短母串 思考记录
- 2017.10.5 高速公路 思考记录
- 2017.10.1 蚯蚓 思考记录
- 2017.10.6 单词 思考记录
- 2017.10.28 压缩 思考记录
- 2017.10.28 排序 思考记录
- 2017.10.1 atcoder TK1 D 思考记录
- 2017.10.1 互不侵犯king 思考记录
- 2017.10.7 括号序列 思考记录
- 2017.10.7 弹飞绵羊 思考记录
- 2017.10.9 放棋子 思考记录
- 2017.10.10 杀人游戏 思考记录
- 2017.10.11 network 网络扩容 思考记录
- 2017.10.13 硬币游戏 思考记录
- 2017.10.17 蜘蛛难题 思考记录
- 2017.10.19 大陆争霸 思考记录
- 2017.10.19 起床困难综合征 思考记录
- 2017.10.23 chess 中国象棋 思考记录
- 15算法课程 66. Plus One
- explicit
- C语言重定义不同的基类型
- rocketmq入门使用
- Java 多线程(PART VI) 线程状态图解
- 2017.10.5 最短母串 思考记录
- centos 安装boost(caffe需要)
- 递归回溯 求N个数的全排列 及 next_permutation的使用
- hdu 2094
- 接水问题
- [BZOJ]3994 [SDOI2015]约数个数和 莫比乌斯 + 分块
- codefoces 868C(二进制,状态压缩)
- 15算法课程 67. Add Binary
- 接口与抽象类的浅析