LA 3907 Puzzle
问题描述:先给你s个禁止串,求不包含禁止串的最长串,如果存在,打印字典序最大。
数据范围:s <= 1000, 禁止串长度不超过50。
分析:不匹配问题实际上等同于匹配问题。假设我们已经有满足条件的串T, 如果加上某个字符c后得到的新串T + c 仍然满足条件,显然
我们便找到了一个更长的串,否则|T|就是所求。我们枚举字符c时,新串是否满足条件取决于原串T的后缀关于所有禁止串在其构成的trie
上的匹配情况,这也就是我们需要并且仅需要维护的信息。具体的说,我们记录串T在trie中匹配最深的节点编号,假设为l(T),当在T尾部
追加字符c时:
l(T) = nex[l(T)][c]
T = T + c
如果更新后得到的l(T)不在任一个禁止节点上,新串便是符合要求的。
如此我们看,若存在一个长度有限的最长串T,那么在T后追加任一个字符c后都会使得l(T + c)落在某个禁止节点上。考虑nex数组的计算:
nex[i][j]表示节点i对应的前缀追加字符j后在trie中匹配最深的节点编号。显然:
nex[i][j] = ch[i][j] ? ch[i][j] : ch[fail[i]][j]]
这里fail[i]表示节点i对应的前缀的后缀(不包括其本身)在trie中匹配最深的节点编号,即AC自动机中的失配函数。
将nex数组合并到ch数组中:
ch[i][j] = nex[i][j]
于是由trie中所有节点关于ch函数构成的一张有向图,并且将某些节点标记为禁止节点当且仅的其对应的前缀为某个禁止串。
因此考虑删去禁止节点后的新图G = (V, A), 合法串与图上的路径有一一对应关系,最长串存在当且仅当 |V| > 1(不能仅包含trie中0节点)
且图中无环。
判断一张有向图是否是DAG可以使用栈的性质,栈中存储dfs搜索经过的链节点,若新点不在链中即可加入,否则证明有环。
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <iostream>
#include <assert.h>
#define pi acos(-1.)
using namespace std;
typedef long long ll;
const int int_inf = 0x3f3f3f3f;
const ll ll_inf = 1ll << ;
const int INT_INF = (int)((1ll << ) - );
const int mod = 1e9 + ;
const double double_inf = 1e30;
typedef unsigned long long ul;
#pragma comment(linker, "/STACK:102400000,102400000")
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define mp make_pair
#define st first
#define nd second
#define keyn (root->ch[1]->ch[0])
#define lson (u << 1)
#define rson (u << 1 | 1)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define type(x) __typeof(x.begin())
#define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++)
#define FOR(i, s, t) for(int i = (s); i <= (t); i++)
#define ROF(i, t, s) for(int i = (t); i >= (s); i--)
#define dbg(x) cout << x << endl
#define dbg2(x, y) cout << x << " " << y << endl
#define clr(x, i) memset(x, (i), sizeof(x))
#define maximize(x, y) x = max((x), (y))
#define minimize(x, y) x = min((x), (y))
#define low_bit(x) ((x) & (-x)) inline int readint(){
int x;
scanf("%d", &x);
return x;
} inline int readstr(char *s){
scanf("%s", s);
return strlen(s);
} class cmpt{
public:
bool operator () (const int &x, const int &y) const{
return x > y;
}
}; int Rand(int x, int o){
//if o set, return [1, x], else return [0, x - 1]
if(!x) return ;
int tem = (int)((double)rand() / RAND_MAX * x) % x;
return o ? tem + : tem;
} void data_gen(){
srand(time());
freopen("in.txt", "w", stdout);
int times = ;
printf("%d\n", times);
while(times--){
int n = Rand(, ), m = Rand(, );
printf("%d %d\n", n, m);
FOR(i, , n){
FOR(j, , m) printf("%c", Rand(, ) + 'a');
putchar('\n');
}
n = Rand(min(, n), ), m = Rand(min(, m), );
printf("%d %d\n", n, m);
FOR(i, , n){
FOR(j, , m) printf("%c", Rand(, ) + 'a');
putchar('\n');
}
}
} struct cmpx{
bool operator () (int x, int y) { return x > y; }
};
int debug = ;
int dx[] = {-, , , };
int dy[] = {, , -, };
//-------------------------------------------------------------------------
const int maxn = 1e3 + ;
const int maxm = ;
int sigma_size, tot;
struct Trie{
int ch[maxn * maxm][];
int sz;
int info[maxn * maxm];
int fail[maxn * maxm];
int ans[maxn * maxm];
int ok[maxn * maxm];
void init() { sz = tot = ; clr(ch[], ); clr(info, ); }
int idx(char c) { return c - 'A'; }
void insert(char *s){
int u = ;
while(*s){
int v = ch[u][idx(*s)];
if(!v) { ch[u][idx(*s)] = v = ++sz; clr(ch[sz], ); }
u = v;
++s;
}
if(!info[u]) info[u] = ++tot;
}
void getFail(){
queue<int> q;
while(!q.empty()) q.pop();
FOR(i, , sigma_size - ) if(ch[][i]) q.push(ch[][i]);
FOR(i, , sigma_size - ) fail[ch[][i]] = ;
while(!q.empty()){
int u = q.front(); q.pop();
FOR(i, , sigma_size - ){
int v = ch[u][i];
if(!v) { ch[u][i] = ch[fail[u]][i]; continue; }
fail[v] = ch[fail[u]][i];
q.push(v);
}
}
} bool vis[maxn * maxm];
bool dfs(int u){
if(vis[u]) return true;
if(ok[u] != -) return ok[u];
if(info[u]) return ok[u] = ;
vis[u] = ;
FOR(i, , sigma_size - ){
int v = ch[u][i];
if(dfs(v)) { vis[u] = ; return ok[u] = ; }
}
vis[u] = ;
return ok[u] = ;
} bool isAcy(){
clr(ok, -), clr(vis, );
return !dfs();
} int __dfs(int u){
if(ans[u] != -) return ans[u];
if(info[u]) return ans[u] = ;
int maxi = ;
FOR(i, , sigma_size - ){
int v = ch[u][i];
int tem = __dfs(v);
maximize(maxi, tem);
}
return ans[u] = maxi + ;
}
int getAns(){
clr(ans, -);
return __dfs();
}
void printAns(int u, int d){
if(info[u]) return;
ROF(i, sigma_size - , ){
int v = ch[u][i];
if(ans[v] == d - ){
if(ans[v] > ) putchar(i + 'A');
printAns(v, d - );
return;
}
}
}
}trie;
int n;
char s[maxm];
//-------------------------------------------------------------------------
int main(){
//data_gen(); return 0;
//C(); return 0;
debug = ;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(debug) freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int T = readint();
while(T--){
sigma_size = readint(), n = readint();
trie.init();
FOR(i, , n){
readstr(s);
trie.insert(s);
}
trie.getFail();
int ans;
if(!trie.isAcy()) ans = ;
else ans = trie.getAns();
if(ans > ) trie.printAns(, ans), putchar('\n');
else puts("No");
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
return ;
}
code:
LA 3907 Puzzle的更多相关文章
- BZOJ 3907: 网格
Description 求不跨过直线 \(y=x\) ,到达 \((n,m)\) 的方案数. Sol 组合数学+高精度. 这个推导过程跟 \(Catalan\) 数是一样的. 答案就是 \(C^{n+ ...
- POJ 1651 Mulitiplication Puzzle
The multiplication puzzle is played with a row of cards, each containing a single positive integer. ...
- Puzzle 面向服务/切面(AOP/IOC)开发框架 For .Net
Puzzle 面向服务/切面AOP开发框架 For .Net AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效 ...
- leggere la nostra recensione del primo e del secondo
La terra di mezzo in trail running sembra essere distorto leggermente massima di recente, e gli aggi ...
- Le lié à la légèreté semblait être et donc plus simple
Il est toutefois vraiment à partir www.runmasterfr.com/free-40-flyknit-2015-hommes-c-1_58_59.html de ...
- HDU5456 Matches Puzzle Game(DP)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5456 Description As an exciting puzzle game for ...
- one recursive approach for 3, hdu 1016 (with an improved version) , permutations, N-Queens puzzle 分类: hdoj 2015-07-19 16:49 86人阅读 评论(0) 收藏
one recursive approach to solve hdu 1016, list all permutations, solve N-Queens puzzle. reference: t ...
- poj3678 Katu Puzzle 2-SAT
Katu Puzzle Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6714 Accepted: 2472 Descr ...
- POJ1651Multiplication Puzzle[区间DP]
Multiplication Puzzle Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8737 Accepted: ...
随机推荐
- Java基础之写文件——使用Formatter对象加载缓冲区(UsingAFormatter)
控制台程序,使用Formatter对象将写入文件的数据准备好. 使用Formatter对象的format()方法,将数据值格式化到视图缓冲区charBuf中. import static java.n ...
- RMQ求区间最值 nlog(n)
转载于:http://blog.csdn.net/xuzengqiang/article/details/7350465 RMQ算法全称为(Range Minimum/Maximum Query)意思 ...
- poj 算法 分类
转载请注明出处:優YoU http://blog.csdn.net/lyy289065406/article/details/6642573 最近AC题:2528 更新时间:2011.09.22 ...
- php4.3.4.4、apache2.0.4.8、mysql 4.0.26、window7 配置过程
apache的安装不需要过程,直接默认安装,下一步 下一步就Ok了. php4的安装: 1 将php-4.0.4-Win32.zip(最新版本4.0.4)解压缩到硬盘的一个目录中,例如解压到E:php ...
- 动画--过渡属性 transition-property
早期在Web中要实现动画效果,都是依赖于JavaScript或Flash来完成.但在CSS3中新增加了一个新的模块transition,它可以通过一些简单的CSS事件来触发元素的外观变化,让效果显得更 ...
- PHP漏洞全解(详细介绍)
转载 http://www.jb51.net/article/31898.htm 针对PHP的网站主要存在下面几种攻击方式: 1.命令注入(Command Injection) 2.eval注入(E ...
- WindowsService 安装后报错: 无法启动计算机“.”上的服务 解决方案
问题 : 根据客户的需求做了一个小程序,需要有对WindowsService 安装,卸载,启动,停止的操作. 编译好之后在我的工程内直接Run 没问题.直接在\bin\Debug 点小程序运行,任何操 ...
- session与cookie的讲解
session_start();//开启session http,无状态性 记录状态SESSION COOKIE SESSION :存储在服务端(器)的:每个人存一份:可以存储任意类型的数据:默认过期 ...
- JSP-08-第三方控件的使用
添加图片 下载 commons-fileupload-1.2.2.jar和commons-io-2.4.jar 导入项目 在添加涂抹的页面设置表单属性 enctype=”multipart/form ...
- InstallShield 下载安装
好久没有写项目了,昨晚加班给一位淘客写了一个Winform小程序, 今早发布,然后发现微软将软件发布的这块内容交给了一个第三方插件 InstallShield, 不知道微软是何用意,我们还是看看如何安 ...