题目链接:[JSOI2009]密码

我们先看第一问:输出方案数

我们把所有给出来的串丢到AC自动机里面去,然后在建出来的\(trie\)图上跑dp

由于\(n\leq 10\)我们很自然的就想到了状压

记\(dp[i][j][sta]\)表示原串匹配到了第\(i\)位,在AC自动机里走到了第\(j\)个节点,已经出现了\(sta\)个单词(压缩状态)的方案数

注意到如果有两个串\(s_i\)和\(s_j\)满足\(s_i\)是\(s_j\)的子串,那么我们所构建的串并不一定必须要有\(s_i\),因为如果有了\(s_j\)那么一定满足了必须有\(s_i\)

那么我们可以确定最终统计答案时的\(sta\),暴力累加即可

接下来就是第二问:输出方案

我么先要考虑一下在什么情况需要做第二问,题目中给的条件是\(ans\leq 42\)

如果此时我们构建的字符串一定有一位“空闲”,即一定有一位可以放置任意字符,而剩下的则必须构成给定的字符串,那么方案数就是\(2*26=52>42\)(该字符可以放在开头和末尾)

因此此时一定不需要输出答案

所以当要进行第二问的时候,一定是只能用所给定的串进行组合

并且不可能出现的重复的串,因为重复的串是可以变成空闲节点的,这样就和上面一样了

预处理出对于任意两个字符串\(s_i,s_j\),\(s_i\)的后\(k\)位和\(s_j\)的前\(k\)位相等的所有\(k\)值

然后暴力dfs排序顺序即可

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int maxd=1000000007,N=100000;
const double pi=acos(-1.0);
typedef long long ll; namespace AC{
struct node{
int ch[27];
int fail,end;
node() {memset(ch,0,sizeof(ch));fail=0;end=0;}
}point[100100];
int cnt; void init()
{
cnt=0;
point[0].fail=0;
} void insert(char *s,int id)
{
int len=strlen(s),i,now=0;
for (i=0;i<len;i++)
{
if (!point[now].ch[s[i]-'a'])
{
point[now].ch[s[i]-'a']=(++cnt);
point[cnt]=node();
}
now=point[now].ch[s[i]-'a'];
}
point[now].end=(1<<(id-1));
} void get_fail()
{
queue<int> q;
int i;
for (i=0;i<26;i++)
{
if (point[0].ch[i])
{
point[point[0].ch[i]].fail=0;
q.push(point[0].ch[i]);
}
}
while (!q.empty())
{
int u=q.front();q.pop();
for (i=0;i<26;i++)
{
if (point[u].ch[i])
{
point[point[u].ch[i]].fail=point[point[u].fail].ch[i];
q.push(point[u].ch[i]);
}
else point[u].ch[i]=point[point[u].fail].ch[i];
}
}
}
}
using namespace AC;
int n,m,len[20],restm,LINK[50][50],ansord[50];
ll dp[2][110][1030];
char s[20][20];
bool del[20]; int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
} int getl(int u,int v)
{
int maxl,i;
for (maxl=min(len[u],len[v]);maxl>0;maxl--)
{
bool ok=1;
for (i=0;i<maxl;i++)
{
if (s[v][i]!=s[u][len[u]-maxl+i]) {ok=0;break;}
}
if (ok) return maxl;
}
return 0;
} int ord[50],tot=0;
bool vis[50];
char ansch[110][110]; void dfs(int dep)
{
if (dep>restm)
{
tot++;
int i,j,now=0;
for (i=1;i<=restm;i++)
{
for (j=LINK[ord[i-1]][ord[i]];j<len[ord[i]];j++)
{
ansch[tot][now++]=s[ord[i]][j];
if (now>n) {tot--;return;}
}
}
if (now<n) tot--;
return;
} int i;
for (i=1;i<=m;i++)
{
if ((del[i]) || (vis[i])) continue;
ord[dep]=i;vis[i]=1;
dfs(dep+1);
vis[i]=0;
}
} bool cmp(int p,int q)
{
int i;
for (i=0;i<n;i++)
if (ansch[p][i]!=ansch[q][i]) return ansch[p][i]<ansch[q][i];
} int main()
{
n=read();m=read();restm=m;
int i,j,k;
for (i=1;i<=m;i++) {scanf("%s",s[i]);len[i]=strlen(s[i]);}
for (i=1;i<=m;i++)
{
for (j=1;j<=m;j++)
{
if ((del[i]) || (del[j]) || (i==j)) continue;
if (len[i]<len[j]) continue;
if (strstr(s[i],s[j])) {del[j]=1;restm--;break;}
}
}
init();
for (i=1;i<=m;i++)
if (!del[i]) insert(s[i],i);
get_fail();
dp[0][0][0]=1;
int now=1,pre=0;
for (i=1;i<=n;i++)
{
memset(dp[now],0,sizeof(dp[now]));
for (j=0;j<=cnt;j++)
{
for (k=0;k<(1<<m);k++)
{
if (dp[pre][j][k])
{
int p;
for (p=0;p<26;p++)
{
int v=point[j].ch[p];
dp[now][v][(k|point[v].end)]+=dp[pre][j][k];
}
}
}
}
now^=1;pre^=1;
}
int all=0;
for (i=1;i<=m;i++)
if (!del[i]) all|=(1<<(i-1));
ll ans=0;
for (i=0;i<=cnt;i++) ans+=dp[pre][i][all];
printf("%lld\n",ans);
if (ans<=42)
{
for (i=1;i<=m;i++)
{
for (j=1;j<=m;j++)
{
if ((del[i]) || (del[j])) continue;
LINK[i][j]=getl(i,j);
}
}
memset(vis,0,sizeof(vis));
dfs(1);
for (i=1;i<=ans;i++) ansord[i]=i;
sort(ansord+1,ansord+1+tot,cmp);
for (i=1;i<=tot;i++)
{
for (j=0;j<n;j++) putchar(ansch[ansord[i]][j]);
puts("");
}
}
return 0;
}

bzoj

bzoj1559 [JSOI2009]密码的更多相关文章

  1. BZOJ1559[JSOI2009]密码——AC自动机+DP+搜索

    题目描述 输入 输出 样例输入 10 2 hello world 样例输出 2 helloworld worldhello 提示 这题算是一个套路题了,多个串求都包含它们的长为L的串的方案数. 显然是 ...

  2. [BZOJ1559][JSOI2009]密码(AC自动机)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1559 2009年的省选题虽然比起现在简单了不少,但对我来说还是很有挑战性的. 首先对于这种多串匹配问 ...

  3. BZOJ1559 [JSOI2009]密码 【AC自动机 + 状压dp】

    题目链接 BZOJ1559 题解 考虑到这是一个包含子串的问题,而且子串非常少,我们考虑\(AC\)自动机上的状压\(dp\) 设\(f[i][j][s]\)表示长度为\(i\)的串,匹配到了\(AC ...

  4. 【BZOJ1559】[JSOI2009]密码(AC自动机,动态规划,搜索)

    [BZOJ1559][JSOI2009]密码(AC自动机,动态规划,搜索) 题面 BZOJ 洛谷 题解 首先求方案数显然是构建\(AC\)自动机之后再状压\(dp\),似乎没有什么好讲的. 现在考虑答 ...

  5. BZOJ 1559: [JSOI2009]密码( AC自动机 + 状压dp )

    建AC自动机后, dp(x, y, s)表示当前长度为x, 在结点y, 包括的串的状态为s的方案数, 转移就在自动机上走就行了. 对于输出方案, 必定是由给出的串组成(因为<=42), 所以直接 ...

  6. P4045 [JSOI2009]密码

    题目 P4045 [JSOI2009]密码 做法 AC自动机+状压+爆搜 建AC自动机是显然的,顺便预处理\(lst_i\)表示\(i\)结点以哪些串结束(二进制) 然后跑状压\(dp[i][j][k ...

  7. [JSOI2009]密码 [AC自动机]

    题面 bzoj luogu 首先看到这题就知道随便暴枚 只要是多项式算法都能过 先常规建AC自动机 注意被别的单词包含的单词没有存在的价值 剩余单词状压 大力dp f[长度][节点编号][状态] \( ...

  8. JSOI2009 密码 和 JSOI2007 文本生成器 和 ZOJ3545 Rescue the Rabbit

    密码 众所周知,密码在信息领域起到了不可估量的作用.对于普通的登陆口令,唯一的破解 方法就是暴力破解一逐个尝试所有可能的字母组合,但这是一项很耗时又容易被发现的工 作.所以,为了获取对方的登陆口令,在 ...

  9. [BZOJ 1559] [JSOI2009] 密码 【AC自动机DP】

    题目链接:BZOJ - 1559 题目分析 将给定的串建成AC自动机,然后在AC自动机上状压DP. 转移边就是Father -> Son 或 Now -> Fail. f[i][j][k] ...

随机推荐

  1. 小L的试卷

    题目描述 小L期末考试结束,高高兴兴放假回家了,可是那么多试卷,老师还要加班批改,有n份试卷由k个老师批改,n份试卷进行了密封编号,由于试卷上的做题情况和书写的规范程序不一样,批改不同的试卷用时也可能 ...

  2. BZOJ1969 航线规划

    给定一个无向图,每次删除一条边,求每次有多少关键边.一条边是关键边,当且仅当从1到n的所有路径都包含这条边.所有时刻图都联通. 考虑倒着做.相当于给一棵树,每次加一条边,这样树上这条边的两个端点间的路 ...

  3. Yii1.1框架关于日志的配置的简单使用

    最近开始接触新项目,新项目用的框架是Yii1.1版本的,通过看框架文档大致熟悉了解了Yii在日志方面的使用. 首先在protected/config/main.php配置文件中加入日志相关配置,如下图 ...

  4. 论学习IT的基本学习方法

    学习还是要通过实践总结这种方式去不断进步,当然这个思想对于生活中的任何事都是相通的,就像我现在做的就是总结一下自己的学习方法,更多的是针对于IT代码这块知识的总结. 我想通过这种博客总结的方式来不断总 ...

  5. java.lang.LinkageError: JAXB 2.0 API is being loaded from the bootstrap classloader

    我的解决办法:    1.如果是application工程,则在程序中打印出         system.out.println(System.getProperty("java.endo ...

  6. remote:error:refusing to update checked out branc

    参考网上的GIt服务器配置流程(http://blog.csdn.net/ice520301/article/details/6142503) 遇到了 http://www.cnblogs.com/c ...

  7. stark组件数据库管理软件的总结

      1.stark - 总结 用到的知识点: 1.单例模式 2.继承 3.反射 4.面向对象 5.modelform 1.注册表 单例模式 site = StarkSite() 2.生成url url ...

  8. flex实现三栏等分布局

    前言 在实际开发中,我们经常会想要实现的一种布局方式就是三栏等分布局,那么我们如何来解决这个问题呢? 解决 方法一:flex 外层容器也就是ul设置display:flex,对项目也就是li设置fle ...

  9. [转帖]2015年时微软Win3.1崩溃迫使巴黎奥利机场短暂关闭

    https://www.ithome.com/html/it/188796.htm IT之家讯 2015年11月14日消息,上周法国巴黎奥利机场因为微软的Windows 3.1系统出现故障不得不迫使所 ...

  10. Windows 下 Mysql8.0.12 的安装方法

    1. 之前在windows 上面安装了 mysql 5.6 还有 mysql 5.7 遇到了几个坑 , 最近想直接安装最新版的 mysql 8.0.12(较新) 发现还是有坑 跟之前的版本不一样 这里 ...