zoukankan      html  css  js  c++  java
  • BZOJ 1195 [HNOI2006]最短母串 (Trie图+状压+bfs最短路)

    BZOJ1195 LOJ10061

    题目大意:给你$n$个模式串,求一个最短且字典序最小的文本串并输出这个串,$n<=12,len<=50$

    首先对所有模式串构造$Trie$图,$Trie$图的性质和$DP$的性质简直是完美契合..

    模式串数量很少,考虑状压

    定义$f[x][s]$表示现在所在$Trie$图内的位置为$x$,已经匹配到的串的状态为$s$,此时需要文本串的最短长度

    转移十分显然,$f[fail_{x}][s|ed[fail_{x}])]=min(f[x][s])+1$

    最后找出最小的$f[x][(1<<n)-1]$

    然而...直接这样转移我们没办法统计答案啊

    考虑把问题放到图上,利用$bfs$队列先进先出的性质,如果我们优先把字典序小的状态推进队列,再通过记录当前状态第一次被更新时的上一层状态$fa[..]$的方式记录路径,跑$bfs$最短路,当队列中出现$s==(1<<n)-1$时立即结束,此时我们求得的一定是长度最短且字典序最小的答案!

    注意可能有相同的串

    注意不要忘了建$fail$树,如果某个节点是某个串的结尾,也要把它是这个串的结尾的信息传递到它在$fail$树中的子树中去!我没传竟然还有70分

      1 #include <queue>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define NN 610
      6 #define MM 4100
      7 #define ll long long 
      8 #define uint unsigned int
      9 #define ull unsigned long long 
     10 #define inf 0x3f3f3f3f
     11 #define idx(x) (x-'A')
     12 using namespace std;
     13 
     14 int n,cte;
     15 int head[NN];
     16 char str[NN];
     17 struct Edge{int to,nxt;}edge[NN*2];
     18 void ae(int u,int v){
     19     cte++;edge[cte].nxt=head[u];
     20     edge[cte].to=v,head[u]=cte;
     21 }
     22 struct node{
     23     int x,s;
     24     node(int x,int s):x(x),s(s){}
     25     node(){}
     26 }fa[NN][MM];
     27 int dis[NN][MM];
     28 namespace AC{
     29 int ch[NN][26],fail[NN],ed[NN],val[NN],tot;
     30 void Build_Trie(char *str,int len,int id)
     31 {
     32     int x=0;
     33     for(int i=1;i<=len;i++){
     34         if(!ch[x][idx(str[i])])
     35             ch[x][idx(str[i])]=++tot,val[tot]=idx(str[i]);
     36         x=ch[x][idx(str[i])];
     37     }ed[x]|=(1<<(id-1));
     38 }
     39 void Build_Fail()
     40 {
     41     queue<int>q;
     42     for(int i=0;i<26;i++)
     43         if(ch[0][i]) q.push(ch[0][i]);
     44     while(!q.empty())
     45     {
     46         int x=q.front();q.pop();
     47         ae(fail[x],x);
     48         for(int i=0;i<26;i++)
     49         {
     50             if(ch[x][i]){
     51                 fail[ch[x][i]]=ch[fail[x]][i];
     52                 q.push(ch[x][i]);
     53             }else{
     54                 ch[x][i]=ch[fail[x]][i];
     55             }
     56         }
     57     }
     58     q.push(0);
     59     while(!q.empty())
     60     {
     61         int x=q.front();q.pop();
     62         for(int j=head[x];j;j=edge[j].nxt){
     63             int v=edge[j].to;
     64             ed[v]|=ed[x];
     65             q.push(v);
     66         }
     67     }
     68 }
     69 node Bfs()
     70 {
     71     queue<node>q;
     72     memset(dis,0x3f,sizeof(dis));
     73     q.push(node(0,0));
     74     dis[0][0]=0;
     75     node k1,k2;
     76     int x,v,s,t;
     77     while(!q.empty())
     78     {
     79         k1=q.front();q.pop();
     80         x=k1.x,s=k1.s;
     81         if(s==(1<<n)-1) return k1;
     82         for(int i=0;i<26;i++)
     83         {
     84             v=ch[x][i],t=s|ed[v];
     85             if(dis[v][t]>dis[x][s]+1){
     86                 dis[v][t]=dis[x][s]+1;
     87                 fa[v][t]=k1;
     88                 q.push(node(v,t));
     89             }
     90         }
     91     }
     92     /*for(int i=1;i<=tot;i++)
     93         printf("%d:%d
    ",i,dis[i][(1<<n)-1]);*/
     94 }
     95 char Ans[NN];
     96 void solve()
     97 {
     98     for(int i=1;i<=n;i++){
     99         scanf("%s",str+1);
    100         int len=strlen(str+1);
    101         Build_Trie(str,len,i);}
    102     Build_Fail();
    103     node ans=Bfs();
    104     node a=ans;
    105     int num=0;
    106     while(a.x||a.s){
    107         Ans[++num]=val[a.x]+'A';
    108         a=fa[a.x][a.s];}
    109     for(int i=num;i>0;i--)
    110         printf("%c",Ans[i]);
    111     puts("");
    112 }
    113 };
    114 
    115 int main()
    116 {
    117     //freopen("t2.in","r",stdin);
    118     scanf("%d",&n);
    119     AC::solve();
    120     return 0;
    121 }
  • 相关阅读:
    js 函数声明和函数表达式的区别
    使用dom4j工具包对xml文件解析
    xml的schema约束
    xml的DTD约束
    C3P0连接池工具类使用
    jdbc连接警告不安全
    java的unity单元测试
    BootStrap容器介绍
    validate插件实现表单效验(二)
    validate插件实现表单效验(一)
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10013212.html
Copyright © 2011-2022 走看看