【AC自动机】最短母串

【题目链接】

https://loj.ac/problem/10061

【题意】

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

【题解】

类似于搜索+二进制记录状态的题目

搜索时利用BFS来跑,每一个结点的位置都可以用状态数组存起来,

判断是否为 (1<<n)- 1 即可。

在输出答案时需要递归实现,所以要一个辅助数组fa来记录上一个结点的位置。

  1 #include<queue>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int N = 6e3+5;
  7 const int M = 2e6+50;
  8 const int Str_N = 605;
  9 int Trie[N][26],fail[N],End[N];
 10 int vis[N][Str_N];
 11 int Q[M],St[M];
 12 int Fa[M];
 13 char str[M];
 14 int Head,Tail;
 15 int n,idx;
 16 char Str[Str_N];
 17 void print(int x){
 18     if(x==1) return ;
 19     print(Fa[x]);
 20     putchar(str[x]+'A');
 21 }
 22 void Insert( char s[] , int Id ){
 23     int p = 0 ;
 24     for(int i=0;s[i];i++){
 25         int t = s[i]-'A';
 26         if( !Trie[p][t] )
 27             Trie[p][t] = ++idx;
 28         p = Trie[p][t];
 29     }
 30     End[p] |= (1<<Id);
 31 }
 32 void Build(){
 33     Head = 1 , Tail = 0;
 34 
 35     for(int i=0;i<26;i++){
 36         if( Trie[0][i] ){
 37             Q[++Tail] = Trie[0][i];
 38             fail[Trie[0][i]] = 0;
 39         }
 40     }
 41 
 42     while( Head <= Tail ){
 43         int u = Q[Head++];
 44 
 45         for(int i=0;i<26;i++){
 46             int To = Trie[u][i];
 47             if( To ){
 48                 fail[To] = Trie[fail[u]][i];
 49                 Q[++Tail] = To ;
 50                 End[To] |= End[fail[To]];
 51             }else{
 52                 Trie[u][i] = Trie[fail[u]][i];
 53             }
 54         }
 55     }
 56 }
 57 void Solve(){
 58     memset(Q,0,sizeof Q );
 59 
 60 
 61     Head = 0 , Tail = 1;
 62     Q[1] = St[1] = 0 ;
 63     vis[0][0] = 1 ;
 64 
 65     while( Head < Tail ){
 66         int u = Q[++Head],S = St[Head];
 67         for(int i=0;i<26;i++){
 68             int To = Trie[u][i];
 69             int Ts = S | End[To] ;
 70             if( vis[Ts][To] ) continue;
 71 
 72             Fa[++Tail] = Head ; Q[Tail] = To ;str[Tail] = i;
 73             vis[Ts][To] = 1 ;St[Tail] = Ts ;
 74 
 75             if( Ts == (1<<n)-1 ){
 76                 print(Tail);
 77                 putchar('\n');
 78                 return ;
 79             }
 80         }
 81     }
 82 }
 83 int main()
 84 {
 85     scanf("%d",&n);
 86     for(int i=0;i<n;i++){
 87         scanf("%s",Str);
 88         Insert(Str,i);
 89     }
 90     Build();
 91     Solve();
 92     return 0;
 93 }
 94 
 95 /*
 96  *
 97 4
 98 HNOI
 99 NOIP
100 NOI
101 IOI
102 
103 HNOIPIOI
104  */
View Code

猜你喜欢

转载自www.cnblogs.com/Osea/p/11367043.html
今日推荐