• HNOI 2006 BZOJ 1195 最短母串


    题面

    问题描述

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

    输入

    第一行是一个正整数n(n<=12),表示给定的字符串的个数。以下的n行,每行有一个全由大写字母组成的字符串。每个字符串的长度不超过50.

    输出

    只有一行,为找到的最短的字符串T。在保证最短的前提下,如果有多个字符串都满足要求,那么必须输出按字典序排列的第一个。

    Sample Input

    2
    ABCD
    BCDABC
    

    Sample Output

    ABCDABC
    

    题解

    AC自动机第一题...
    实际上这题用到的是trie图, 状压DP即可. 每个节点记录在什么状态下被经过, 用于去重. 时间复杂度和空间复杂度都是(2^nnL)

    #include <cstdio>
    #include <cstring>
    #include <deque>
    
    const int N = 12, LEN = 50;
    int n;
    char ans[N * LEN];
    struct ACautomaton
    {
    	struct node
    	{
    		node *suc[26], *fl;
    		int vst[1 << N], ed;
    		inline node()
    		{
    			for(int i = 0; i < 26; ++ i)
    				suc[i] = NULL;
    			memset(vst, 0, sizeof(vst));
    			ed = -1;
    		}
    	}*rt;
    	inline ACautomaton()
    	{
    		rt = new node;
    		rt->fl = rt;
    	}
    	inline void insert(char *str, int len, int id)
    	{
    		node *u = rt;
    		for(int i = 0; i < len; u = u->suc[str[i] - 'A'], ++ i)
    			if(u->suc[str[i] - 'A'] == NULL)
    				u->suc[str[i] - 'A'] = new node;
    		u->ed = id;
    	}
    	inline void build()
    	{
    		static std::deque<node*> que;
    		que.clear();
    		for(int i = 0; i < 26; ++ i)
    			if(rt->suc[i] != NULL)
    				rt->suc[i]->fl = rt, que.push_back(rt->suc[i]);
    		for(; ! que.empty(); que.pop_front())
    		{
    			node *u = que.front();
    			for(int i = 0; i < 26; ++ i)
    				if(u->suc[i] != NULL)
    				{
    					node *p = u->fl;
    					for(; p != rt && p->suc[i] == NULL; p = p->fl);
    					u->suc[i]->fl = p->suc[i] == NULL ? p : p->suc[i];
    					que.push_back(u->suc[i]);
    				}
    			for(int i = 0; i < 26; ++ i)
    				if(u->suc[i] == NULL)
    					u->suc[i] = u->fl->suc[i];
    		}
    	}
    	struct state
    	{
    		node *u;
    		int lst, rec, c;
    		inline state(node *_u, int _lst, int _rec, int _c)
    		{
    			u = _u, lst = _lst, rec = _rec, c = _c;
    		}
    		inline state() {}
    	};
    	inline void work()
    	{
    		static state que[(1 << N) * N * LEN];
    		int L = 0, R = 0;
    		que[R ++] = state(rt, -1, 0, -1);
    		for(; ; L ++)
    		{
    			state cur = que[L];
    			node *u = cur.u;
    			int rec = cur.rec;
    			if(~ u->ed)
    				rec |= 1 << u->ed, u->vst[rec] = 1;
    			if(rec == (1 << n) - 1)
    				break;
    			for(int i = 0; i < 26; ++ i)
    				if(u->suc[i] != NULL && ! u->suc[i]->vst[rec])
    					que[R ++] = state(u->suc[i], L, rec, i), u->suc[i]->vst[rec] = 1;
    		}
    		int len = 0;
    		for(; L; L = que[L].lst)
    			ans[len ++] = 'A' + que[L].c;
    		for(int i = len - 1; ~ i; -- i)
    			putchar(ans[i]);
    	}
    }ACA;
    int main()
    {
    	
    	#ifndef ONLINE_JUDGE
    	freopen("BZOJ1195.in", "r", stdin);
    	freopen("BZOJ1195.out", "w", stdout);
    	#endif
    
    	scanf("%d
    ", &n);
    	for(int i = 0; i < n; ++ i)
    	{
    		static char str[LEN];
    		scanf("%s", str);
    		ACA.insert(str, strlen(str), i);
    	}
    	ACA.build();
    	ACA.work();
    }
    
  • 相关阅读:
    CTFHub题解-技能树-Web-文件上传(00截断、双写后缀)【三】
    CTFHub题解-技能树-Web-文件上传(.htaccess、MIME绕过、文件头检查)【二】
    CTFHub题解-技能树-Web-文件上传(无验证、前端验证)【一】
    CTFHub题解-技能树-Web-SQL注入(Cookie注入、UA注入、Refer注入)【三】
    记一次centos7重启后docker无法启动的问题
    ctfshow——web_AK赛
    Windows10安装MongoDB
    centOS7安装docker和docker-compose
    xray—学习笔记
    ctfhub技能树—sql注入—过滤空格
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/7144930.html
Copyright © 2020-2023  润新知