这个题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]);
}

2017.10.5 最短母串 思考记录相关推荐

  1. 2017.10.1 atcoder TK1 D 思考记录

    题目大意:给你10^5个物品,有重量和价值, 求重量按位或不超过k的物品的最大价值 首先它是不可以dp的,因为与运算对于背包不能离散,所以考虑模拟入手 从最高位往下找,来保证小于k 若这一位是1,则这 ...

  2. 2017.9.20 回文串 思考记录

    这个题官方解法是 manacher+sa. 但pam诞生之后这个题就变成了模板题.. 事实证明,科技是第一解题力 网上的pam讲解感觉很迷啊,,核心思想一张图就搞定了: 黑色箭头就是指向以右端点为结尾 ...

  3. 2017.10.23 chess 中国象棋 思考记录

    这种题的一般解法: 1. 发现状压可以搞,然后发现状态爆炸 2.考虑状态特点,一共只有几种可能的状态 3.考虑可不可以只对状态进行计数 4.离散统计贡献 码: #include<iostream ...

  4. 2017.10.19 起床困难综合征 思考记录

    2333noi送分题 首先暴力试每个数有些二进制位是会重复算的,,所以就考虑能否把每个二进制位独立考虑 老性质:二进制运算每一位独立 所以二进制dp,如果这一位输入1,是多少,输入0,是多少 然后按二 ...

  5. 2017.10.11 network 网络扩容 思考记录

    第一问是网络流. 第二问是费用流,但之前的边依然是可以用的,所以每个点决策:用原来的流量    购买一条流量,扫每条边加进去就可以了 然后限制流出为k 码: #include<iostream& ...

  6. 2017.10.7 弹飞绵羊 思考记录

    ..这个题根据弹后的关系是很容易想出一个森林的..修改连接关系就是cut和link.. 但是分块的做法似乎十分优越,,好写好调.所以学一下分块的写法 首先每一个区间的信息都是可以做到O(1)查询的.. ...

  7. 2017.10.1 互不侵犯king 思考记录

    ..没想到做的这么顺利 首先n<=⑨.. 所以状压这个⑨ 然后枚举状态转移累加即可 f[行数][最上层排布情况][已经用了几个] 最后    Σf[n][i][k]   0<=i<2 ...

  8. BZOJ1195[HNOI2006]最短母串——AC自动机+BFS+状态压缩

    题目描述 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 输入 第一行是一个正整数n(n<=12),表示给定的字符串的 ...

  9. 2782: [HNOI2006]最短母串

    2782: [HNOI2006]最短母串 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 3  Solved: 2 [Submit][Status][W ...

最新文章

  1. 单链表:头结点和头指针的实现方式
  2. Spring 配置JNDI(连接池)
  3. delphi json
  4. ARM(IMX6U)ARM Cortex-A7中断系统(GPIO按键中断驱动蜂鸣器)
  5. 鼎信诺审计前端取数工具_给2019前端的5个建议
  6. NP管理器v3.0.25 一键添加去除apk对话框等
  7. windows下git bash中文乱码解决办法
  8. uniapp 移动端上传文件_基于 uniapp 实现动态路由和动态 Tabbar
  9. (进阶)LeetCode(258)——各位相加(JavaScript)
  10. 快速使用js验证输入的数字类型
  11. 学以致用二---配置Centos7.2 基本环境
  12. php steam 第三方登录,Steam第三方登录
  13. Java架构师 JD汇总
  14. 8. 机器人正运动学---DH坐标系建立技巧
  15. 计算机ps特效教程,制作木质电脑桌的PS滤镜教程
  16. Gradle入门教程学习笔记
  17. ILSVRC2015_DET.tar.gz下载地址
  18. 计算机组装所需硬件,电脑组装机配置清单
  19. 蓝桥杯—大胖子走迷宫—广搜
  20. opencv19:轮廓凸包,距离与匹配

热门文章

  1. fatal: could not read Username for 'https://github.com': No such file or directory
  2. 韩顺平php视频笔记79 80 错误和异常处理的机制 错误处理器 错误触发器
  3. 计算机图形学E6——倒水问题emm和OpenGL没啥关系
  4. 各种服务器系统桌面,服务器系统云桌面
  5. python selenium爬虫需要账号和密码登陆的网页_如何使用selenium和requests组合实现登录页面...
  6. 用循环语句求2^0+2^1+........+2^63 (C语言)
  7. flutter java混编_有赞 Flutter 混编方案
  8. 分时系统是计算机网络嘛,简述计算机网络与分时多用户系统多机系统分布式系统的区别...
  9. 获取页眉值vba_VBA抓取股票历史数据的整体表处理
  10. python 日志 logging模块(详细解析)