UVA 1399 Puzzle 求一个最长的串使得该串不包含任何禁止串为子串 AC自动机 + DP +dfs判环
来源:互联网 发布:安卓防沉迷软件 编辑:程序博客网 时间:2024/05/17 16:44
【解题参考blog】http://blog.csdn.net/acm_10000h/article/details/48878645
【题意】给定K和N,表示有K种不同的字符,N个禁止串,求一个最长的串使得该串不包含任何禁止串为子串。如果存在循环或者不能构成的话,输出No!
【解题方法】实际上就是Trie图上的最长路,先对模式串建立AC自动机,之后在AC自动机上跑最长路。无限长的情况就是trie图形成了环,这个dfs判环即可!
【代码君】
////Created by just_sort 2016/10/13//Copyright (c) 2016 just_sort.All Rights Reserved//#include <set>#include <map>#include <queue>#include <stack>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;const int maxn = 55555;const int maxm = 26;struct Acautomata{ int ch[maxn][maxm],val[maxn],fail[maxn],root,sz; int newnode(){ val[sz] = 0; memset(ch[sz], 0, sizeof(ch[sz])); return sz++; } void init(){ sz = 0; root = newnode(); } void insert(char *s,int v){ int len = strlen(s); int u = root; for(int i = 0; i < len; i++){ int now = s[i] - 'A'; if(!ch[u][now]){ ch[u][now] = newnode(); } u = ch[u][now]; } val[u] = v; } void build(){ queue <int> q; fail[0] = 0; for(int i = 0; i < maxm; i++){ int u = ch[0][i]; if(u){ q.push(u); fail[u] = 0; } } while(q.size()) { int u = q.front(); q.pop(); for(int i = 0; i < maxm; i++){ int v = ch[u][i]; if(!v){ ch[u][i] = ch[fail[u]][i]; continue; } q.push(v); int j = fail[u]; while(j && !ch[j][i]) j = fail[j]; fail[v] = ch[j][i]; val[v] |= val[fail[v]]; } } }}ac;int n,m;int vis1[maxn],vis2[maxn],dp[maxn],path[maxn][2];bool dfs1(int u){ vis2[u] = 1; for(int i = 0; i < n; i++) { int v = ac.ch[u][i]; if(vis1[v]) return 1; if(!vis2[v] && !ac.val[v]) { vis1[v] = 1; if(dfs1(v)) return true; vis1[v] = 0; } } return false;}int dfs2(int u){ if(vis1[u]) return dp[u]; vis1[u] = 1; dp[u] = 0; for(int i = n - 1; i >= 0; i--) { if(!ac.val[ac.ch[u][i]]) { int tmp = dfs2(ac.ch[u][i]) + 1; if(dp[u] < tmp) { dp[u] = tmp; path[u][0] = ac.ch[u][i]; path[u][1] = i; } } } return dp[u];}void print_path(int u){ if(path[u][0] == -1) return ; printf("%c", 'A' + path[u][1]); print_path(path[u][0]);}int main(){ int T; scanf("%d",&T); while(T--) { ac.init(); scanf("%d%d",&n,&m); for(int i = 0; i < m; i++){ char op[55]; scanf("%s",op); ac.insert(op,1); } ac.build(); memset(vis1, 0, sizeof(vis1)); memset(vis2, 0, sizeof(vis2)); vis1[0] = 1; if(dfs1(0)) { printf("No\n"); } else{ memset(vis1, 0, sizeof(vis1)); memset(path, -1, sizeof(path)); if(dfs2(0) == 0) { printf("No\n"); } else { print_path(0); puts(""); } } } return 0;}
0 0
- 求一个最长的串使得该串不包含任何禁止串为子串 AC自动机+DP +dfs判环 UVA 1399 - Puzzle
- UVA 1399 Puzzle 求一个最长的串使得该串不包含任何禁止串为子串 AC自动机 + DP +dfs判环
- 随机生成的S不包含任何一个串的概率 AC自动机+概率DP UVA 11468 Substring
- UVA 1399 - Puzzle(AC自动机+DP)
- 求一个只包含0,1,-1的数组,和为0的最长子串的长度
- uva 1399 - Puzzle(AC自动机)
- 求字符串中不包含重复字符的最长子串的长度
- 求字符串内不包含重复字符的最长子串的集合
- 求字符串内不包含重复字符的最长子串
- AC自动机,概率,递推(子串,UVA 11468)
- 求字符串中包含唯一字符的最长子串
- SMOJ 1767 子串个数 (AC自动机+状压DP)
- 求最长不重复子串
- 求最长不重复子串
- 求最长不重复子串
- 求最长不重复子串---LeetCode3
- 求最长不重复子串
- UVA 1449 Dominating Patterns (LA4670) 出现次数最多的子串 ac自动机
- Missing ios Distribution signing identity for xxxx
- wireshark
- 矩阵连乘问题
- VS2010 编译X64 Boost 库
- C++ Primer Plus (第六版)第五章编程练习参考答案
- UVA 1399 Puzzle 求一个最长的串使得该串不包含任何禁止串为子串 AC自动机 + DP +dfs判环
- JSON怎么对字符串进行系列化和反系列化,HTML5保存到本地文件
- 第七周求两个数加减乘除
- 【Test 2016-10-2】light {枚举}
- 内部类 Object类 final关键字 多态
- python中遇到的几个问题
- ArrayList部分源码学习笔记
- LevelDB:Cache源码精读——缓存
- 基于堆的优先队列和堆排序