[BZOJ1559][JSOI2009]密码(AC自动机)
http://www.lydsy.com/JudgeOnline/problem.php?id=1559
2009年的省选题虽然比起现在简单了不少,但对我来说还是很有挑战性的。
首先对于这种多串匹配问题,第一个想到的就应该是AC自动机。
还是老套路,f[i][j]表示走到字符串的第i位,现在在自动机上的第j位时的信息。增加一维n位的压位表示各个串是否都被匹配到了。
但是这里有个问题,如果S1包含了S2,那么我们只需要S1被匹配就能保证S2也被匹配,而不需要在自动机上走到S2的位置。
这样我们预处理的时候先删掉所有被包含的字符串(反正L<=25,N<=10怎样都不会T),然后直接在自动机上跑DP即可。
现在考虑ans<=42的情况,可以发现,这种情况下原串不可能有任何一个自由字母。因为只要存在一个自由字母和一个模式串,则至少存在2*26=52>42种方案。所以对于这种情况我们只需用最暴力的方法DFS穷举所有长度为L且恰好包含了每个模式串的方案并按字典序排序。
这里有一个技巧,border[i][j]表示第i个串后缀和第j个串的前缀中完全匹配的最长的串的长度(也就是KMP中的nxt[]),方便穷举。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mem(a) memset(a,0,sizeof(a))
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; int n,m,L,ch[][],q[],num[],fail[],sz,bor[][],g1,g[],a1,len[],rk[],vis[],del[];
char str[][],a[][];
ll f[][][]; int border(int x,int y){
for (int i=min(len[x],len[y]); i>=; i--){
int flag=;
rep(j,,i-) if (str[x][len[x]-i+j]!=str[y][j]){ flag=; break; }
if (!flag) return i;
}
return ;
} void ins(int x){
int now=;
rep(i,,len[x]-){
int s=str[x][i]-'a';
if (!ch[now][s]) ch[now][s]=++sz;
now=ch[now][s];
}
num[now]=<<(x-);
} void getfail(){
int st=,ed=;
rep(i,,) if (ch[][i]) q[++ed]=ch[][i];
while (st<ed){
int x=q[++st];
rep(i,,)
if (ch[x][i]) q[++ed]=ch[x][i],fail[ch[x][i]]=ch[fail[x]][i];
else ch[x][i]=ch[fail[x]][i];
}
} void dfs(int x){
if (x>m){
a1++; int l=;
rep(i,,g1) rep(j,bor[g[i-]][g[i]],len[g[i]]-) a[a1][++l]=str[g[i]][j];
if (l!=L) a1--; return;
}
rep(i,,n) if (!del[i] && !vis[i]) vis[i]=,g[++g1]=i,dfs(x+),vis[i]=,g1--;
} bool cmp(int x,int y){
rep(i,,L) if (a[x][i]!=a[y][i]) return a[x][i]<a[y][i];
return ;
} bool chk(int x,int y){
rep(i,,len[y]-len[x]){
int j=;
for (; j<len[x]; j++) if ((str[x][j])!=str[y][i+j]) break;
if (j==len[x]) return ;
}
return ;
} void dp(){
int now=; f[][][]=;
rep(i,,L-){
now=now^; mem(f[now]);
rep(j,,sz) rep(k,,(<<n)-)
if (f[now^][j][k])
rep(l,,){
int x=ch[j][l],y=k;
if (num[x]) y|=num[x];
f[now][x][y]+=f[now^][j][k];
}
}
ll ans=; int s=;
rep(i,,n) if (!del[i]) s+=<<(i-);
rep(i,,sz) ans+=f[now][i][s];
printf("%lld\n",ans);
if (ans<=){
dfs(); rep(i,,a1) rk[i]=i;
sort(rk+,rk+a1+,cmp);
rep(i,,a1){ rep(j,,L) putchar(a[rk[i]][j]); puts(""); }
}
} int main(){
freopen("bzoj1559.in","r",stdin);
freopen("bzoj1559.out","w",stdout);
scanf("%d%d",&L,&n); m=n;
rep(i,,n) scanf("%s",str[i]),len[i]=strlen(str[i]);
rep(i,,n) rep(j,,n) bor[i][j]=border(i,j);
rep(i,,n) rep(j,,n) if (len[j]>len[i] && !del[j] && !del[i] && chk(i,j)) del[i]=,m--;
rep(i,,n) if (!del[i]) ins(i);
getfail(); dp();
return ;
}
[BZOJ1559][JSOI2009]密码(AC自动机)的更多相关文章
- BZOJ1559[JSOI2009]密码——AC自动机+DP+搜索
题目描述 输入 输出 样例输入 10 2 hello world 样例输出 2 helloworld worldhello 提示 这题算是一个套路题了,多个串求都包含它们的长为L的串的方案数. 显然是 ...
- BZOJ 1559: [JSOI2009]密码( AC自动机 + 状压dp )
建AC自动机后, dp(x, y, s)表示当前长度为x, 在结点y, 包括的串的状态为s的方案数, 转移就在自动机上走就行了. 对于输出方案, 必定是由给出的串组成(因为<=42), 所以直接 ...
- [JSOI2009]密码 [AC自动机]
题面 bzoj luogu 首先看到这题就知道随便暴枚 只要是多项式算法都能过 先常规建AC自动机 注意被别的单词包含的单词没有存在的价值 剩余单词状压 大力dp f[长度][节点编号][状态] \( ...
- BZOJ1559 [JSOI2009]密码 【AC自动机 + 状压dp】
题目链接 BZOJ1559 题解 考虑到这是一个包含子串的问题,而且子串非常少,我们考虑\(AC\)自动机上的状压\(dp\) 设\(f[i][j][s]\)表示长度为\(i\)的串,匹配到了\(AC ...
- [BZOJ1559]密码 AC自动机+状压
问题 K: [JSOI2009]密码 时间限制: 1 Sec 内存限制: 64 MB 题目描述 众所周知,密码在信息领域起到了不可估量的作用.对于普通的登陆口令,唯一的破解 方法就是暴力破解一逐个尝 ...
- bzoj1559 [JSOI2009]密码
题目链接:[JSOI2009]密码 我们先看第一问:输出方案数 我们把所有给出来的串丢到AC自动机里面去,然后在建出来的\(trie\)图上跑dp 由于\(n\leq 10\)我们很自然的就想到了状压 ...
- 【BZOJ4327】JSOI2012 玄武密码 AC自动机
[BZOJ4327]JSOI2012 玄武密码 Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香 ...
- BZOJ4327 [JSOI2012] 玄武密码 [AC自动机]
题目传送门 玄武密码 Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神 ...
- Vijos P1951 玄武密码 (AC自动机)
描述 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此. 很多年后,人们终于在 ...
随机推荐
- 【BZOJ】1036 [ZJOI2008]树的统计Count
[算法]树链剖分+线段树 [题解]模板题,见http://www.cnblogs.com/onioncyc/p/6207462.html 调用线段数时要用新编号pos[i] !!! #include& ...
- 引用类型 ( 对象定义 )——Date 类型
本文地址:http://www.cnblogs.com/veinyin/p/7607743.html 1 创建日期对象 var date = new Date(); 2 可以给日期对象传值 2.1 ...
- UIWebView---iOS-Apple苹果官方文档翻译
CHENYILONG Blog UIWebView---iOS-Apple苹果官方文档翻译 UIWebView 技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博h ...
- 旅游(CSUST省赛选拔赛2+状压dp+最短路)
题目链接:http://csustacm.com:4803/problem/1016 题目: 思路:状压dp+最短路,比赛的时候有想到状压dp,但是最短路部分写挫了,然后就卡死了,对不起出题人~dis ...
- NYOJ 409 郁闷的C小加(三) (字符串处理)
题目链接 描述 聪明的你帮助C小加解决了中缀表达式到后缀表达式的转换(详情请参考"郁闷的C小加(一)"),C小加很高兴.但C小加是个爱思考的人,他又想通过这种方法计算一个表达式的值 ...
- vc 播放音乐
#include <vfw.h> #pragma comment(lib,"vfw32.lib") ● 简单实现 要实现一个播放器,首先要先建立一个MF ...
- Skipping 'Android SDK Tools, revision 24.0.2'; it depends on 'Android SDK Platform-tools, revision 20' which was not installed.
前几天,同事问我eclipse android sdk怎么不能更新. 更新界面是显示(mirrors.neusoft.edu.cn:80),但是不能更新. 问题描述如下: URL not found: ...
- Mysql储存过程1: 设置结束符与储存过程创建
#显示储存过程 show procedure status; #设置结束符 delimiter $; #创建储存过程 create procedure procedure_name() begin - ...
- Git和Github简单教程【转】
转自:https://www.cnblogs.com/schaepher/p/5561193.html#clone 原文链接:Git和Github简单教程 网络上关于Git和GitHub的教程不少,但 ...
- tera term通过ttl脚本 自动连接服务器(转自http://www.cnblogs.com/wxb0328/p/teraterm.html)
转自http://www.cnblogs.com/wxb0328/p/teraterm.html 在现在的这个公司一直使用tera term来远程连接服务器,感觉很方便,特别是它的ttl脚本配置的自动 ...