zoukankan      html  css  js  c++  java
  • bzoj1195 [HNOI2006]最短母串 AC 自动机+状压+bfs

    题目传送门

    https://lydsy.com/JudgeOnline/problem.php?id=1195

    题解

    建立 AC 自动机,然后构建出 trie 图。

    然后直接在 trie 图上走。但是我们需要经过每一个串。

    所以我们处理一下每个点代表了哪些串,然后把状态加入进 bfs 状态。

    然后 bfs 就可以了。


    (O(n))

    #include<bits/stdc++.h>
    
    #define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
    #define dbg(...) fprintf(stderr, __VA_ARGS__)
    #define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
    #define fi first
    #define se second
    #define pb push_back
    
    template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
    template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}
    
    typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
    
    template<typename I> inline void read(I &x) {
    	int f = 0, c;
    	while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    	x = c & 15;
    	while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    	f ? x = -x : 0;
    }
    
    const int N = 12 + 1;
    const int M = 50 + 1;
    const int NM = 12 * 50 + 1;
    const int NP = (1 << 12);
    const int NMP = 12 * 50 * ((1 << 12) - 1) + 1;
    
    int n, m, nod;
    int q[NMP], q2[NMP], fr[NM][NP];
    char s[N], ans[NM];
    struct Node { int c[26], fa, v; char s; } t[NM];
    
    inline void ins(char *s, int id) {
    	int n = strlen(s + 1), o = 0;
    	for (int i = 1; i <= n; ++i) {
    		if (!t[o].c[s[i] - 'A']) t[o].c[s[i] - 'A'] = ++nod, t[nod].s = s[i];
    		o = t[o].c[s[i] - 'A'];
    	}
    	t[o].v |= 1 << (id - 1);
    }
    inline void build() {
    	int hd = 0, tl = 0;
    	for (int i = 0; i < 26; ++i) if (t[0].c[i]) q[++tl] = t[0].c[i];
    	while (hd < tl) {
    		int x = q[++hd]; t[x].v |= t[t[x].fa].v;
    		for (int i = 0; i < 26; ++i)
    			if (t[x].c[i]) t[t[x].c[i]].fa = t[t[x].fa].c[i], q[++tl] = t[x].c[i];
    			else t[x].c[i] = t[t[x].fa].c[i];
    	}
    }
    
    inline void work() {
    	int hd = 0, tl = 1, S = (1 << n) - 1;
    	q[tl] = 0, q2[tl] = 0, fr[0][0] = -1;
    	while (hd < tl) {
    		int x = q[++hd];
    		int s = q2[hd];
    //		dbg("x = %d, s = %d
    ", x, s);
    		for (int i = 0; i < 26; ++i) if (t[x].c[i]) {
    			int y = t[x].c[i], ss = s | t[y].v;
    //			dbg("y = %d, ss = %d
    ", y, ss);
    			if (!fr[y][ss]) {
    				fr[y][ss] = hd, q[++tl] = y, q2[tl] = ss;
    //				dbg("****** y = %d, ss = %d
    ", y, ss);
    				if (ss == S) {
    					int len = 0, z = y, zs = ss, zz;
    					while (~fr[z][zs]) ans[++len] = t[z].s, zz = fr[z][zs], z = q[zz], zs = q2[zz];
    					while (len) putchar(ans[len--]);
    					puts("");
    //					dbg("*********
    ");
    					return;
    				}
    				assert(fr[y][ss]);
    			}
    		}
    	}
    }
    
    inline void init() {
    	read(n);
    	for (int i = 1; i <= n; ++i) scanf("%s", s + 1), ins(s, i);
    	build();
    //	dbg("*************
    ");
    }
    
    int main() {
    #ifdef hzhkk
    	freopen("hkk.in", "r", stdin);
    #endif
    	init();
    	work();
    	fclose(stdin), fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    网站安全编程 黑客入侵 脚本黑客 高级语法入侵 C/C++ C# PHP JSP 编程
    【算法导论】贪心算法,递归算法,动态规划算法总结
    cocoa2dx tiled map添加tile翻转功能
    8月30日上海ORACLE大会演讲PPT下载
    【算法导论】双调欧几里得旅行商问题
    Codeforces Round #501 (Div. 3) B. Obtaining the String (思维,字符串)
    Codeforces Round #498 (Div. 3) D. Two Strings Swaps (思维)
    Educational Codeforces Round 89 (Rated for Div. 2) B. Shuffle (数学,区间)
    洛谷 P1379 八数码难题 (BFS)
    Educational Codeforces Round 89 (Rated for Div. 2) A. Shovels and Swords (贪心)
  • 原文地址:https://www.cnblogs.com/hankeke/p/bzoj1195.html
Copyright © 2011-2022 走看看