题目

P4045 [JSOI2009]密码

做法

AC自动机+状压+爆搜

建AC自动机是显然的,顺便预处理\(lst_i\)表示\(i\)结点以哪些串结束(二进制)

然后跑状压\(dp[i][j][k]\)表\(i\)长度现在在\(j\)结点已经出现的串\(k\),理解:自由结点则由根节点\(0\)传递

毒瘤的地方在于输出串,显然\(ans<=42\)时,没有自由结点

两遍爆搜:

\(~~~~~\)第一遍预处理\(visit[i][j][k]\),其中\(i,j,k\)和\(dp\)数组相同,数组内存的值表示是否有效

\(~~~~~\)第二遍直接跑\(visit\),有效才能搜过去

My complete

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
typedef int LL;
const LL maxn=200;
LL L,n,nod,Up;
long long ans;
LL lst[maxn],son[maxn][26],fail[maxn];
long long dp[30][maxn][1<<11];
inline void Insert(char *s,LL id){
LL Len(strlen(s+1)),now(0);
for(LL i=1;i<=Len;++i){
LL c(s[i]-'a');
if(son[now][c]==0) son[now][c]=++nod;
now=son[now][c];
}lst[now]=1<<(id-1);
}
inline void F_trie(){
queue<LL>que;
for(LL i=0;i<26;++i)
if(son[0][i]) que.push(son[0][i]);
while(que.size()){
LL u(que.front()); que.pop();
lst[u]|=lst[fail[u]];
for(LL i=0;i<26;++i){
LL v(son[u][i]);
if(v){
fail[v]=son[fail[u]][i];
que.push(v);
}else son[u][i]=son[fail[u]][i];
}
}
}
LL sta[30],visit[30][maxn][1<<11];
void Dfs(LL len,LL now,LL bit){
if(len==L){
for(LL i=0;i<L;++i)
printf("%c",sta[i]+'a');printf("\n");
return;
}
for(LL i=0;i<26;++i){
LL v(son[now][i]);
if(v==0||visit[len+1][v][bit|lst[v]]!=1) continue;
sta[len]=i;
Dfs(len+1,v,bit|lst[v]);
}
}
bool First(LL len,LL now,LL bit){
if(visit[len][now][bit]==1) return true;
else if(visit[len][now][bit]==-1) return false;
else if(len==L){
visit[len][now][bit]=-1; return false;
}
for(LL i=0;i<26;++i){
LL v(son[now][i]);
if(v==0) continue;
if(First(len+1,v,bit|lst[v]))
visit[len][now][bit]=1;
}
if(visit[len][now][bit]!=1){
visit[len][now][bit]=-1;
return false;
}return true;
}
inline void Solve(){
for(LL i=0;i<L;++i)
for(LL u=0;u<=nod;++u)
for(LL pre=0;pre<Up;++pre)
if(dp[i][u][pre]) First(i,u,pre);
Dfs(0,0,0);
}
char s[maxn];
int main(){
scanf("%d %d",&L,&n);
for(LL i=1;i<=n;++i){
scanf(" %s",s+1),
Insert(s,i);
}F_trie();
Up=(1<<n);
dp[0][0][0]=1;
for(LL i=1;i<=L;++i)
for(LL u=0;u<=nod;++u)
for(LL pre=0;pre<Up;++pre){
if(dp[i-1][u][pre]==0) continue;
for(LL k=0;k<26;++k){
LL v(son[u][k]);
dp[i][v][pre|lst[v]]+=dp[i-1][u][pre];
}
}
for(LL i=0;i<=nod;++i){
if(dp[L][i][Up-1])
visit[L][i][Up-1]=1,
ans+=dp[L][i][Up-1];
else visit[L][i][Up-1]=-1;
}
printf("%lld\n",ans);
if(ans<=42)
Solve();
return 0;
}/*
*/

最新文章

  1. 【bzoj3674】 可持久化并查集加强版
  2. Python (1) - 7 Steps to Mastering Machine Learning With Python
  3. 关于sqoop与datax。 和sqoop to oracle插件OraOop
  4. LYK 快跑!(run)
  5. IntelliJ IDEA调整控制台输出字体大小
  6. HDU 4799 LIKE vs CANDLE 树形dp
  7. PS字体工具字体显示不出来
  8. JAVA面向对象的多态性
  9. Triangle (第8届山东省赛的某题)
  10. Android 音视频开发学习思路
  11. # 20175333曹雅坤《Java程序设计》第2周学习总结
  12. python数据类型分类以及运算类型
  13. PairWork-电梯调度程序结对编程
  14. Jquery对当前日期的操作(格式化当前日期)
  15. Android的硬件抽象层模块编写规范
  16. linux和windows动态库加载路径区别
  17. jquery 事件监听方法
  18. How To Disable MacBook ProTrackpad
  19. shiro session过期后ajax请求跳转(转)
  20. JavaWeb 没用

热门文章

  1. PHP面试题及答案解析(5)—数据结构与算法
  2. VLOOKUP函数的用法
  3. GoogleMap的鼠标点击标注、搜索和设置城市的简单应用
  4. CSS3:选择器
  5. ORACLE 表空间使用率查询
  6. 微服务网关哪家强?一文看懂Zuul, Nginx, Spring Cloud, Linkerd性能差异
  7. strpos 判断字符串是否存在
  8. saltstack内置state模块user
  9. Android创建library工程
  10. Latex中參考文献排序