zoukankan      html  css  js  c++  java
  • [BZOJ1195]最短母串

    1195: [HNOI2006]最短母串

    Time Limit: 10 Sec  Memory Limit: 32 MB

    Description

    给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串。

    Input

    第一行是一个正整数n(n<=12),表示给定的字符串的个数。以下的n行,每行有一个全由大写字母组成的字符串。每个字符串的长度不超过50.

    Output

    只有一行,为找到的最短的字符串T。在保证最短的前提下,如果有多个字符串都满足要求,那么必须输出按字典序排列的第一个。

    Sample Input

    2
    ABCD
    BCDABC

    Sample Output

    ABCDABC
     
    题解:
    一开始的确想到了状压……但是没有想到后面的操作……
    而且这个题让我不得不打数组版……痛心疾首。
    如果我们按照AC自动机来做这道题,我们可以这样考虑:
    建好trie图之后,从根节点跑一个BFS最短路,并且按照A~Z的顺序往下走,
    那么我们就实现了“最短”和“字典序最小”。
    而对于字符串,我们可以用状压来记录每个串是否出现。
    代码见下:
     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 const int K=1<<12;
     5 const int N=610;
     6 short n,cnt,bit[20];
     7 char s[15][60],ans[N],c[N*K];
     8 short val[N],ch[N][26],f[N];
     9 bool vis[N][K];
    10 int from[N*K],q[N],hd,tl;
    11 short state[N*K],point[N*K];
    12 inline void get_fail()
    13 {
    14     hd=0,tl=0;
    15     for(int i=0;i<26;i++)
    16         if(ch[0][i])q[tl++]=ch[0][i];
    17     while(hd^tl)
    18     {
    19         int rt=q[hd++];
    20         for(int i=0;i<26;i++)
    21         {
    22             int u=f[rt];
    23             if(ch[rt][i])
    24             {
    25                 q[tl++]=ch[rt][i];
    26                 while(u&&!ch[u][i])u=f[u];
    27                 f[ch[rt][i]]=ch[u][i];
    28                 val[ch[rt][i]]|=val[ch[u][i]];
    29             }
    30             else
    31                 ch[rt][i]=ch[u][i];
    32         }
    33     }
    34 }
    35 inline void get_ans()
    36 {
    37     hd=0,tl=1;
    38     while(hd^tl)
    39     {
    40         int u=point[hd],st=state[hd];
    41         if(st==bit[n]-1)
    42         {
    43             int id=0;
    44             while(hd)ans[++id]=c[hd],hd=from[hd];
    45             while(id>=1)putchar(ans[id]),id--;
    46             return;
    47         }
    48         for(int i=0;i<26;i++)
    49         {
    50             if(!vis[ch[u][i]][st|val[ch[u][i]]])
    51             {
    52                 point[tl]=ch[u][i];
    53                 c[tl]=i+'A',from[tl]=hd;
    54                 state[tl]=st|val[ch[u][i]];
    55                 vis[point[tl]][state[tl]]=1;
    56                 tl++;
    57             }
    58         }
    59         hd++;
    60     }
    61 }
    62 int main()
    63 {
    64     scanf("%d",&n);
    65     bit[0]=1;for(int i=1;i<=n;i++)bit[i]=bit[i-1]<<1;
    66     for(int i=1;i<=n;i++)
    67     {
    68         scanf("%s",s[i]);
    69         int rt=0;int m=strlen(s[i]);
    70         for(int j=0;j<m;j++)
    71         {
    72             int d=s[i][j]-'A';
    73             if(!ch[rt][d])ch[rt][d]=++cnt;
    74             rt=ch[rt][d];
    75         }
    76         val[rt]|=bit[i-1];
    77     }
    78     get_fail();get_ans();
    79 }
    [BZOJ1195]
  • 相关阅读:
    Ubuntu 下安装QT
    Ubuntu下配置Samba服务器
    二进制、八进制、十进制、十六进制之间转换
    Oracle_创建和管理表
    Oracle_数据处理
    单例模式
    01.DesignParttern设计模式,简单工厂,工厂方法,抽象工厂三大工厂的区别与联系
    MAC系统中的轻量级图像浏览器Lyn1.9
    MAC系统的绝佳截图工具Snipaste
    MAC系统的绝佳截图工具Snipaste
  • 原文地址:https://www.cnblogs.com/LadyLex/p/7106888.html
Copyright © 2011-2022 走看看