• [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)
    ",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();
    }
    
    
  • 相关阅读:
    IDEA创建一个javaweb工程(在module中)以及配置Tomcat
    晨会复盘
    cnblog 笔记思路
    Mysql执行计划-extra
    Mysql执行计划分析-type(access_type)
    Mysql执行计划-selectType
    刻意训练
    MYSQL执行计划
    个人展望-程序员职业规划
    服务拆分原则
  • 原文地址:https://www.cnblogs.com/birchtree/p/12346769.html
Copyright © 2020-2023  润新知