[BZOJ1195] [HNOI2006] 最短母串(AC自动机+状压bfs)

[BZOJ1195] [HNOI2006] 最短母串(AC自动机+状压bfs)

题面

给定n个字符串(S1,S2...Sn),要求找到一个最短的字符串T,使得这n个字符串都包含这个字符串
\(n \leq 12,|S| \leq 50\)

分析

在自动机上bfs,bfs的深度就是字符串长度。\(n\)很小,因此把匹配情况压成一个二进制数即可。注意还要记录前驱,方便输出方案。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset> 
#define maxn 600
#define maxb (1<<12)
#define maxc 26 
using namespace std;
struct AC_automaton{
    int ch[maxn+5][maxc];
    int fail[maxn+5];
    int cnt_end[maxn+5];
    int id[maxn+5];
    int ptr;
    void insert(char *s,int num){
        int n=strlen(s+1);
        int x=0;
        for(int i=1;i<=n;i++){
            int c=s[i]-'A';
            if(!ch[x][c]) ch[x][c]=++ptr;
            x=ch[x][c];
        }
        cnt_end[x]|=(1<<(num-1));
    } 
    void get_fail(){
        queue<int>q;
        for(int i=0;i<maxc;i++) if(ch[0][i]) q.push(ch[0][i]);
        while(!q.empty()){
            int x=q.front();
            q.pop();
            
            for(int i=0;i<maxc;i++){
                if(ch[x][i]){
                    fail[ch[x][i]]=ch[fail[x]][i];
                    cnt_end[ch[x][i]]|=cnt_end[ch[fail[x]][i]];
                    q.push(ch[x][i]);
                }else{
                    ch[x][i]=ch[fail[x]][i];
                }
            }
        }
    }
    inline int size(){
        return ptr; 
    } 
}T;

int n;
char s[maxn+5];
int vis[maxn+5][maxb+5];

struct node{
    int x;
    int sta;
    int last;
    int cr;
    node(){
        
    }
    node(int _x,int _sta,int _last,int _cr){
        x=_x;
        sta=_sta;
        last=_last;
        cr=_cr;
    }
}q[maxn*maxb+5];
void bfs(){
    static char ans[maxn+5];
    int head=1,tail=0;
    q[++tail]=node(node(0,0,0,0));
    while(head<=tail){
//      printf("(%d,%d,%d,%d)\n",q[head].x,q[head].sta,q[head].last,q[head].cr);
        if(q[head].sta==(1<<n)-1){
            int sz=0;
            for(int i=head;i>0;i=q[i].last){
                ans[++sz]=q[i].cr+'A';
            }
            for(int i=sz-1;i>=1;i--) putchar(ans[i]);
            return;
        }
        for(int i=0;i<4;i++){
            int nex=T.ch[q[head].x][i];
            int ss=q[head].sta|T.cnt_end[nex];
            if(!vis[nex][ss]){
                q[++tail]=node(nex,ss,head,i);
                vis[nex][ss]=1;
            }
        }
        head++;
    }
    
}
int main(){
    int sum=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",s+1);
        T.insert(s,i);
        sum+=strlen(s+1);
    }
    T.get_fail();
    bfs();
}

猜你喜欢

转载自www.cnblogs.com/birchtree/p/12346769.html
今日推荐