洛谷$P4045\ [JSOI2009]$密码 $dp$+$AC$自动机
正解:$dp$+$AC$自动机+搜索
解题报告:
首先显然先建个$AC$自动机,然后考虑设$f_{i,j,k}$表示长度为$i$,现在在$AC$自动机的第$j$个位置,已经表示出来的串的状态为$k$的方案数,直接转移就好.
然后考虑输出方案.首先一定不存在可以随便填的位置.
挺显然的随便说下昂,首先如果有一个可以随便填的位置,就有26种可能.然后可以给这个位置和字符串交换位置,就至少有2种可能,这时候就已经至少有$2\times 26=52$了,所以一定不存在可以随便填的位置.
所以直接$O(!n)$爆搜$QwQ$,$over$
因为爆搜真的很麻烦,所以我直接开了个$vector$在$dp$转移的时候顺便记了下方案.
但是挺容易$MLE$的,所以我把第一维滚了下.
然后还有一个注意点是每次转移完之后没用的$vector$清空下不然真的$MLE$到飞起$kk$
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define gc getchar()
#define ll long long
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i) const int N=100+10,M=(1<<10)+10;
int len,n,nod_cnt,tot,nw=1,pre;
ll f[2][N][M],ans;
bool vis[N];
char s[N];
vector<string>as[2][N][M],an;
struct node{int to[27],zt,fail;}nod[N]; il int read()
{
rc ch=gc;ri x=0;rb y=1;
while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
if(ch=='-')ch=gc,y=0;
while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
return y?x:-x;
}
il void insert(ri num)
{
scanf("%s",s+1);ri l=strlen(s+1),nw=0;
rp(i,1,l)
{
if(!nod[nw].to[s[i]-'a'])nod[nw].to[s[i]-'a']=++nod_cnt;
nw=nod[nw].to[s[i]-'a'];
}
nod[nw].zt=1<<num;
}
il void build()
{
queue<int>Q;
rp(i,0,25)if(nod[0].to[i])Q.push(nod[0].to[i]);
while(!Q.empty())
{
ri nw=Q.front();Q.pop();
rp(i,0,25)
if(nod[nw].to[i])Q.push(nod[nw].to[i]),nod[nod[nw].to[i]].fail=nod[nod[nw].fail].to[i];
else nod[nw].to[i]=nod[nod[nw].fail].to[i];
nod[nw].zt|=nod[nod[nw].fail].zt;
}
} signed main()
{
//freopen("4045.in","r",stdin);freopen("4045.out","w",stdout);
len=read();n=read();rp(i,1,n)insert(i-1);build();tot=(1<<n)-1;
f[0][0][0]=1;as[0][0][0].push_back("");
rp(i,1,len)
{
rp(j,0,nod_cnt)
{
rp(k,0,tot)
{
if(f[pre][j][k])
{
rp(t,0,25)
{
ri nwzt=k|nod[nod[j].to[t]].zt;
f[nw][nod[j].to[t]][nwzt]+=f[pre][j][k];
if(f[nw][nod[j].to[t]][nwzt]<=42)
{
ri sz=as[pre][j][k].size();
rp(tt,0,sz-1)as[nw][nod[j].to[t]][nwzt].push_back(as[pre][j][k][tt]+(char)(t+'a'));
}
}
}
f[pre][j][k]=0;if(!as[pre][j][k].empty())as[pre][j][k].clear();
}
}
nw^=1;pre^=1;
}
nw^=1;
rp(i,0,nod_cnt)
{
ans+=f[nw][i][(1<<n)-1];
if(ans<=42){ri sz=as[nw][i][(1<<n)-1].size();rp(j,0,sz-1)an.push_back(as[nw][i][(1<<n)-1][j]);}
}
printf("%lld\n",ans);if(ans>42)return 0;
sort(an.begin(),an.end());rp(i,0,ans-1)cout<<an[i]<<endl;
return 0;
}
随机推荐
- C# 设计模式 责任链
责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个 ...
- Linux中使用gcc编译文件
一个项目中可能有多个cpp文件,在linux下编译执行过程如下: g++ main.cpp distance.cpp ./a.out 即可一起编译两个文件,然后执行该程序.
- android学习——android项目的的目录结构
然后我们看一下Helloword的程序目录: 我们可以看到 大致有的文件: 1. MainHelloWorld.java文件 2. R.java文件 3. android.jar文件 4. RE ...
- php开发微信支付获取用户地址
http://mp.weixin.qq.com/s/uNpWE_Z5RZ48PDIWkmGBYQ 使用微信获取地址信息是和微信支付一道申请的,微信支付申请通过,就可以使用该功能. 微信商城中,使用微信 ...
- H3C 各种视图之间的关系
- @NOI模拟2017.06.30 - T1@ Left
目录 @description@ @solution@ @accepted code@ @details@ @description@ JOHNKRAM 最近在研究排序网络,但他发现他不会制作比较器, ...
- iptables发布内部网络服务器
要使因特网上的计算机访问到内部网的FTP服务器.WEB服务器,在做为防火墙的计算机上应添加以下规则: 1. echo 1 > /proc/sys/net/ipv4/ip_forward 2. 发 ...
- js实现div的碰壁反弹效果
文章地址 https://www.cnblogs.com/sandraryan/ 需求: 写一个div,让div在父级进行匀速运动,碰到父级上下左右的边框,就向反方向运动. 碰壁反弹在游戏制作中很常用 ...
- 机器学习降维方法概括, LASSO参数缩减、主成分分析PCA、小波分析、线性判别LDA、拉普拉斯映射、深度学习SparseAutoEncoder、矩阵奇异值分解SVD、LLE局部线性嵌入、Isomap等距映射
机器学习降维方法概括 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u014772862/article/details/52335970 最近 ...
- Flex AIR使用ADT命令打包 ipa
1. 配置环境变量. 2. 测试adt命令 3. 将ShepherdPhone0815.mobileprovision和 my.p12文件都放入编译好的工程目录下,如下图: 4.切换到上述编译好的目录 ...