NC20049. [HNOI2006]最短母串
描述
输入描述
第一行是一个正整数n(n ≤ 12),表示给定的字符串的个数。
以下的n行,每行有一个全由大写字母组成的字符串。每个字符串的长度不超过50.
输出描述
只有一行,为找到的最短的字符串T。
在保证最短的前提下,如果有多个字符串都满足要求,那么必须输出按字典序排列的第一个。
示例1
输入:
2 ABCD BCDABC
输出:
ABCDABC
C++11(clang++ 3.9) 解法, 执行用时: 211ms, 内存消耗: 20568K, 提交时间: 2019-07-26 20:45:50
#include<bits/stdc++.h> typedef long long ll; using namespace std; #define N 521 int tr[26][N],ed[N],tot,fail[N],n; void insert(char a[],int pos){ int i,now=0; for(i=0;a[i];i++){ int x=a[i]-'A'; if(!tr[x][now])tr[x][now]=++tot; now=tr[x][now]; } ed[now]|=(1<<pos); } void build(){ int i; queue<int>Q; for(i=0;i<26;i++)if(tr[i][0])Q.push(tr[i][0]); while(!Q.empty()){ int x=Q.front();Q.pop(); for(i=0;i<26;i++){ if(tr[i][x])fail[tr[i][x]]=tr[i][fail[x]],ed[tr[i][x]]|=ed[fail[tr[i][x]]],Q.push(tr[i][x]); else tr[i][x]=tr[i][fail[x]]; } } } struct TP{ int num,st,pos; }; int vis[N][1<<13],path[N*(1<<13)],letter[N*(1<<13)]; char ans[N*N*N]; char a[N]; int main(){ int i; scanf("%d",&n); for(i=0;i<n;i++){ scanf("%s",a); insert(a,i); } build(); queue<TP>Q; Q.push((TP){0,ed[0],0}); vis[0][ed[0]]=1; int last=0,tot=0; while(!Q.empty()){ int num=Q.front().num,st=Q.front().st,pos=Q.front().pos;Q.pop(); if(st==(1<<n)-1){ while(last){ ans[--num]='A'+letter[last]; last=path[last]; } printf("%s",ans); break; } for(i=0;i<26;i++){ int nxt=tr[i][pos],nst=st|ed[nxt]; if(vis[nxt][nst])continue; vis[nxt][nst]=1; path[++tot]=last; letter[tot]=i; Q.push((TP){num+1,nst,nxt}); } last++; } return 0; }