• 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 }
  • 相关阅读:
    UML简介
    Servlet过滤器基础及使用场景
    eclipse maven配置问题:org.apache.maven.archiver.mavenarchiver.getmanifest
    maven中的groupId和artifactId 区分
    Spring中的控制反转和依赖注入
    SQL语句、PL/SQL块和SQL*Plus命令之间的区别
    Mybatis核心类生命周期和管理
    MyBatis Generator 下划线转驼峰命名
    修改maven默认仓库(即repository)的路径
    MyBatis SqlSessionFactory的几种常见创建方式
  • 原文地址:https://www.cnblogs.com/refun/p/10028975.html
Copyright © 2020-2023  润新知