zoukankan      html  css  js  c++  java
  • BZOJ 1195: [HNOI2006]最短母串

    1195: [HNOI2006]最短母串

    Time Limit: 10 Sec  Memory Limit: 32 MB
    Submit: 1346  Solved: 450
    [Submit][Status][Discuss]

    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

    HINT

     

    Source

     
    [Submit][Status][Discuss]

    不明白网上为啥题解都写的那么复杂,还说可以hack别人,好怕怕哦……

     1 #include<cstdio>
     2 #define N 605
     3 #define M (1<<12)
     4 #define chr char
     5 #define sht short
     6 chr s[55];
     7 int n,tt=1;
     8 sht fl[N];
     9 int ed[N];
    10 sht ch[N][26];
    11 int q[N*M],l,r;
    12 sht f[N][M];
    13 int p[N][M];
    14 sht c[N][M];
    15 sht stk[N],tp;
    16 main(){
    17     scanf("%d",&n);
    18     for(int i=0;i<n;++i){
    19         scanf("%s",s); int t=1;
    20         for (char *c=s;*c;++c){
    21             if(!ch[t][*c-'A'])
    22                 ch[t][*c-'A']=++tt;
    23             t=ch[t][*c-'A'];
    24         }
    25         ed[t]|=1<<i;
    26     }
    27     fl[1]=1;
    28     for(int i=0;i<26;++i)
    29         if(ch[1][i])
    30             fl[q[r++]=ch[1][i]]=1;
    31         else
    32             ch[1][i]=1;
    33     while(l!=r){
    34         int t=q[l++];
    35         for(int i=0;i<26;++i)
    36             if(ch[t][i])
    37                 fl[q[r++]=ch[t][i]]=ch[fl[t]][i],
    38                 ed[ch[t][i]]|=ed[ch[fl[t]][i]];
    39             else
    40                 ch[t][i]=ch[fl[t]][i];
    41     }
    42     l=r=0;q[r++]=1<<n;f[1][0]=1;
    43     while(l!=r){
    44         int id=q[l]>>n,bt=q[l]&((1<<n)-1);++l;
    45         for(int i=0;i<26;++i){
    46             int v=ch[id][i],b=bt|ed[v];
    47             if(f[v][b])continue;
    48             f[v][b]=1;q[r++]=v<<n|b; 
    49             p[v][b]=id<<n|bt;
    50             c[v][b]=i;
    51             if(b==(1<<n)-1)goto out;
    52         }
    53     }
    54 out:int id=q[r-1]>>n,bt=(1<<n)-1;
    55     while(id!=1){
    56         stk[++tp]=c[id][bt];
    57         int pp=p[id][bt];
    58         id=pp>>n;
    59         bt=pp&((1<<n)-1);
    60     }
    61     while(tp)putchar('A'+stk[tp--]);puts("");
    62 }

    @Author: YouSiki

  • 相关阅读:
    Android中Chronometer 计时器和震动服务控件
    Android中几种常用的话框
    Android通过长按图片设置为壁纸
    Android把图片保存到SQLite中
    激活Win10
    SQL 语句解决实际问题
    在Foxmail邮件客户端登录263企业邮箱
    Visual Studio 安装VS10x CodeMAP
    开发常见问题汇总
    Java笔记:编写第一个Java程序
  • 原文地址:https://www.cnblogs.com/yousiki/p/6498304.html
Copyright © 2011-2022 走看看