zoukankan      html  css  js  c++  java
  • BZOJ1195:[HNOI2006]最短母串(AC自动机,BFS)

    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

    Solution

    先建好$AC$自动机,然后每个结束点用状压标记一下包含状态。

    从根开始$BFS$,找到答案就停止,这样可以保证最短。

    每次扩展按字典序从小到大扩展,这样可以保证字典序最小。

    $BFS$的时候存下前驱输出答案就好了。

    建立$fail$指针的时候,当$now$点建完的时候,要往上暴跳$fail$,把$fail$上包含状态并到$now$上!我沙茶忘了这里找了好久错误TAT

    卡空间真的丧病……

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<queue>
     5 #define N (601)
     6 using namespace std;
     7 
     8 struct Node{int p,S,id;};
     9 int n,sz,cnt,Son[N][26],End[N],Fail[N];
    10 int pre[N*3000],ans[N*3000];
    11 bool vis[N][1<<12];
    12 queue<int>q;
    13 queue<Node>Q;
    14 char s[N];
    15 
    16 void Insert(char s[],int id)
    17 {
    18     int now=0;
    19     for (int i=0,l=strlen(s); i<l; ++i)
    20     {
    21         int x=s[i]-'A';
    22         if (!Son[now][x]) Son[now][x]=++sz;
    23         now=Son[now][x];
    24     }
    25     End[now]|=(1<<(id-1));
    26 }
    27 
    28 void Build_Fail()
    29 {
    30     for (int i=0; i<26; ++i)
    31         if (Son[0][i]) q.push(Son[0][i]);
    32     while (!q.empty())
    33     {
    34         int now=q.front(); q.pop();
    35         for (int i=0; i<26; ++i)
    36         {
    37             if (!Son[now][i])
    38             {
    39                 Son[now][i]=Son[Fail[now]][i];
    40                 continue;
    41             }
    42             Fail[Son[now][i]]=Son[Fail[now]][i];
    43             q.push(Son[now][i]);
    44         }
    45         int t=Fail[now];
    46         while (t && !End[t]) t=Fail[t];
    47         End[now]|=End[t];
    48     }
    49 }
    50 
    51 void Print(int x)
    52 {
    53     if (!x) return;
    54     Print(pre[x]); printf("%c",ans[x]+'A');
    55 }
    56 
    57 void Solve()
    58 {
    59     Q.push((Node){0,0,0});
    60     vis[0][0]=true;
    61     while (!Q.empty())
    62     {
    63         Node tmp=Q.front(); Q.pop();
    64         int p=tmp.p,S=tmp.S;
    65         if (S==(1<<n)-1) {Print(tmp.id); return;}
    66         for (int i=0; i<26; ++i)
    67             if (!vis[Son[p][i]][S|End[Son[p][i]]])
    68             {
    69                 vis[Son[p][i]][S|End[Son[p][i]]]=true;
    70                 ++cnt; ans[cnt]=i; pre[cnt]=tmp.id;
    71                 Q.push((Node){Son[p][i],S|End[Son[p][i]],cnt});
    72             }
    73     }
    74 }
    75 
    76 int main()
    77 {
    78     scanf("%d",&n);
    79     for (int i=1; i<=n; ++i)
    80         scanf("%s",s),Insert(s,i);
    81     Build_Fail(); Solve();
    82 }
  • 相关阅读:
    Delphi Canvas的FillRect(const Rect: TRect) 函数的作用
    将多个jpg文件以追加形式合并成一个文件_delphi教程 bmp 合并 http://www.west.cn/www/info/58058-1.htm
    早期原版翎风(LF)引擎(M2)源码(Delphi)
    Application.Restore不起作用了
    delphi 函数isiconic 函数 判断窗口是否最小化
    delphi SetWindowPos改变窗体位置和状态
    Linux 软件看门狗 watchdog
    使用Linux C编写看门狗(watchdog)程序
    Linux编程之《看门狗进程》
    Mac PWN入门巩固篇(六)
  • 原文地址:https://www.cnblogs.com/refun/p/10028975.html
Copyright © 2011-2022 走看看