HDU2825 Wireless Password


Problem Description

Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless network in the building. Liyuan did not know the password of the network, but he got some important information from his neighbor. He knew the password consists only of lowercase letters ‘a’-‘z’, and he knew the length of the password. Furthermore, he got a magic word set, and his neighbor told him that the password included at least k words of the magic word set (the k words in the password possibly overlapping).

For instance, say that you know that the password is 3 characters long, and the magic word set includes ‘she’ and ‘he’. Then the possible password is only ‘she’.

Liyuan wants to know whether the information is enough to reduce the number of possible passwords. To answer this, please help him write a program that determines the number of possible passwords.

Input

There will be several data sets. Each data set will begin with a line with three integers n m k. n is the length of the password (1<=n<=25), m is the number of the words in the magic word set(0<=m<=10), and the number k denotes that the password included at least k words of the magic set. This is followed by m lines, each containing a word of the magic set, each word consists of between 1 and 10 lowercase letters ‘a’-‘z’. End of input will be marked by a line with n=0 m=0 k=0, which should not be processed.

Output

For each test case, please output the number of possible passwords MOD 20090717.

Sample Input

10 2 2

hello

world

4 1 1

icpc

10 0 0

0 0 0

Sample Output

2

1

14195065


我觉得挺好的一道题。。一开始只知道是DP,然后写了一个循环,后面发现不能重复计算,然后改成了状压DP,改成了队列实现DP,上线是步数小于等于长度,然后每一次DP转移将步数加1就好了,然后或一下当前存在的状态。

处理fail指针的时候做两个小优化,一个是在处理的时候就把fail链上的id全部统计起来,二个是把失配后跳到的节点直接储存成儿子节点

然后注意开一下取模的操作,防止TLE


#include<bits/stdc++.h>
using namespace std;
#define N 110
#define Mod 20090717
struct Node{
int fail,id,ch[26];
void clean(){
fail=id=0;
memset(ch,0,sizeof(ch));
}
}t[N];
struct Node1{int id,tmp,now;};
int n,m,p,tot=0;
int dp[N][26][1025],c[1025];
bool vis[N][26][1025];
char s[20][N];
void init(){
tot=1;
t[0].clean();t[1].clean();
for(int i=0;i<26;i++)t[0].ch[i]=1;
memset(dp,0,sizeof(dp));
}
int index(char c){return c-'a';}
void insert(char *s,int id){
int len=strlen(s),u=1;
for(int i=0;i<len;i++){
int tmp=index(s[i]);
if(!t[u].ch[tmp])
t[t[u].ch[tmp]=++tot].clean();
u=t[u].ch[tmp];
}
t[u].id=1<<(id-1);
}
void buildFail(){
queue<int> q;q.push(1);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<26;i++){
int w=t[u].ch[i],v=t[u].fail;
while(!t[v].ch[i])v=t[v].fail;
v=t[v].ch[i];
if(w){
t[w].fail=v;
t[w].id|=t[v].id;//***
q.push(w);
}else t[u].ch[i]=v;//***
}
}
}
void solve(){
queue<Node1> qn;
qn.push((Node1){1,0,0});
dp[1][0][0]=1;
while(!qn.empty()){
Node1 u=qn.front();qn.pop();
vis[u.id][u.tmp][u.now]=0;
if(u.tmp>n)continue;
for(int i=0;i<26;i++){
int id=t[u.id].ch[i],tmp=u.tmp+1,now=u.now|t[id].id;
dp[id][tmp][now]+=dp[u.id][u.tmp][u.now];
if(dp[id][tmp][now]>Mod)dp[id][tmp][now]-=Mod;
if(!vis[id][tmp][now]){
vis[id][tmp][now]=1;
qn.push((Node1){id,tmp,now});
}
}
}
}
int count(int t){
int ans=0;
while(t){
if(t&1)ans++;
t>>=1;
}
return ans;
}
int main(){
for(int i=0;i<1024;i++)c[i]=count(i);
while(1){
scanf("%d%d%d",&n,&m,&p);
if(!n)break;
init();//初始化
for(int i=1;i<=m;i++){
scanf("%s",s[i]);
insert(s[i],i);
}
buildFail();
solve();
int ans=0,up=1<<m;
for(int i=0;i<up;i++)if(c[i]>=p)
for(int j=1;j<=tot;j++){
ans+=dp[j][n][i];
if(ans>Mod)ans-=Mod;
}
printf("%d\n",ans);
}
return 0;
}

HDU2825 Wireless Password 【AC自动机】【状压DP】的更多相关文章

  1. HDU2825 Wireless Password —— AC自动机 + 状压DP

    题目链接:https://vjudge.net/problem/HDU-2825 Wireless Password Time Limit: 2000/1000 MS (Java/Others)    ...

  2. hdu2825 Wireless Password(AC自动机+状压dp)

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission ...

  3. HDU-2825 Wireless Password(AC自动机+状压DP)

    题目大意:给一系列字符串,用小写字母构造出长度为n的至少包含k个字符串的字符串,求能构造出的个数. 题目分析:在AC自动机上走n步,至少经过k个单词节点,求有多少种走法. 代码如下: # includ ...

  4. 【HDU2825】Wireless Password (AC自动机+状压DP)

    Wireless Password Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u De ...

  5. hdu_2825_Wireless Password(AC自动机+状压DP)

    题目链接:hdu_2825_Wireless Password 题意: 给你m个串,问长度为n至少含k个串的字符串有多少个 题解: 设dp[i][j][k]表示考虑到长度为i,第j个自动机的节点,含有 ...

  6. hdu 2825 aC自动机+状压dp

    Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

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

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

  8. HDU 3247 Resource Archiver(AC自动机 + 状压DP + bfs预处理)题解

    题意:目标串n( <= 10)个,病毒串m( < 1000)个,问包含所有目标串无病毒串的最小长度 思路:貌似是个简单的状压DP + AC自动机,但是发现dp[1 << n][ ...

  9. zoj3545Rescue the Rabbit (AC自动机+状压dp+滚动数组)

    Time Limit: 10 Seconds      Memory Limit: 65536 KB Dr. X is a biologist, who likes rabbits very much ...

  10. hdu 4057--Rescue the Rabbit(AC自动机+状压DP)

    题目链接 Problem Description Dr. X is a biologist, who likes rabbits very much and can do everything for ...

随机推荐

  1. jni使用问题总结

    参考: https://blog.csdn.net/fred_lzy/article/details/53159138 https://blog.csdn.net/avi3/article/detai ...

  2. 《用 Python 学微积分》笔记 3

    <用 Python 学微积分>原文见参考资料 1. 16.优化 用一个给定边长 4 的正方形来折一个没有盖的纸盒,设纸盒的底部边长为 l,则纸盒的高为 (4-l)/2,那么纸盒的体积为: ...

  3. ThinkPHP开发笔记-视图

    1.如果要在模板中输出变量,必须在在控制器中把变量传递给模板,系统提供了assign方法对模板变量赋值,无论何种变量类型都统一使用assign赋值,而且assign方法必须在display和show方 ...

  4. tcpdump实用笔记

    前言:本文是关于tcpdump抓包的文章,是一篇对于本人而言比较实用轻便的文章,如您需要更详细的介绍,以下链接的文章相比最适合您,而且网络知识要非常扎实才能理解透彻: tcpdump详细介绍 简介:用 ...

  5. PHP 数组遍历 foreach 语法结构

    foreach 语法结构用于遍历数组. foreach() PHP foreach() 语法结构用于遍历操作或输出数组,foreach() 仅能用于遍历数组或对象,当试图将其用于其它数据类型或者一个未 ...

  6. 解决:make:cc 命令未找到的解决方法

    安装Redis的时候报这个错误 原因:未安装gcc 解决方法:安装gcc 自动安装,包括依赖库[root@VM_220_111_centos redis-3.2.9]# yum -y install ...

  7. Codeforces Round #349 (Div. 2)

    第一题直接算就行了为了追求手速忘了输出yes导致wa了一发... 第二题技巧题,直接sort,然后把最大的和其他的相减就是构成一条直线,为了满足条件就+1 #include<map> #i ...

  8. [myeclipse]@override报错问题

    @Override是JDK5 就已经有了,但有个小小的Bug,就是不支持对接口的实现,认为这不是Override 而JDK6 修正了这个Bug,无论是对父类的方法覆盖还是对接口的实现都可以加上@Ove ...

  9. 5.彻底理解volatile

    1. volatile简介 在上一篇文章中我们深入理解了java关键字synchronized,我们知道在java中还有一大神器就是关键volatile,可以说是和synchronized各领风骚,其 ...

  10. Java笔试之输入输出

    在校招笔试中,有的时候我们要自己设计输入输出,下面罗列一些常见的输入输出: 首先把输入包加载进来: import java.util.* ; 一 ,输入 1,输入一个整数,浮点数,输入一个数组 : p ...