题意:

给n。m,k ,再给出m个单词

问长度为n的字符串。至少在m个单词中含有k个的组成方案有多少种。

思路:

因为m最大是10,所以能够採取状压的思想

首先建立trie图,在每一个单词的结束节点标记一个mark=(1<<id),id为单词的编号

然后须要注意的,对于每一个节点,应该顺着fail指针遍历一遍,

把全部的mark取一个并集。

由于就是假设单词出现包括的话,比方 she和he 我拿了she,事实上等于两个都拿了。

dp[i][j][k]  i步在节点j状态k的方案数

然后就是一个四重循环了

应该是非常好理解的

最后遍历在n步时,各个节点。然后判一下状态是否里面拿了不少于k个物品的个数

做一个累加就是答案了!

做dp的时候 顺便滚动了一下

代码:

#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
#include"map"
#include"string"
#define inf 9999999
#define mod 20090717
using namespace std;
int triecont;
struct trie
{
int mark,id;
trie *next[27],*fail;
trie()
{
memset(next,0,sizeof(next));
fail=NULL;
mark=id=0;
}
};
trie *root,*node[123];
void init(char *v,int k)
{
trie *p=root;
for(int i=0; v[i]; i++)
{
int tep=v[i]-'a';
if(p->next[tep]==NULL)
{
p->next[tep]=new trie();
node[triecont]=p->next[tep];
p->next[tep]->id=triecont++;
}
p=p->next[tep];
}
p->mark|=(1<<k);
}
void getac()
{
queue<trie*>q;
q.push(root);
while(!q.empty())
{
trie *p;
p=q.front();
q.pop();
for(int i=0; i<26; i++)
{
if(p->next[i]==NULL)
{
if(p==root) p->next[i]=root;
else p->next[i]=p->fail->next[i];
}
else
{
if(p==root) p->next[i]->fail=root;
else p->next[i]->fail=p->fail->next[i];
q.push(p->next[i]);
trie *tep=p->next[i];
if(p!=root) p->next[i]->mark|=p->next[i]->fail->mark;
}
}
}
}
int judge(int x)
{
int ans=0;
for(int i=0; i<10; i++)
{
if(x&(1<<i)) ans++;
}
return ans;
}
__int64 dp[2][105][1025];
int main()
{
int n,m,num;
while(scanf("%d%d%d",&n,&m,&num),(n+m+num))
{
memset(node,0,sizeof(node));
triecont=0;
root=new trie();
node[triecont]=root;
root->id=triecont++;
if(num>m)
{
puts("0");
continue;
}
for(int i=0; i<m; i++)
{
char x[12];
scanf("%s",x);
init(x,i);
}
getac();
for(int j=0; j<triecont; j++) for(int k=0; k<(1<<m); k++) dp[0][j][k]=0;
dp[0][0][0]=1;
for(int i=1; i<=n; i++)
{
for(int j=0; j<triecont; j++) for(int k=0; k<(1<<m); k++) dp[i%2][j][k]=0;
for(int j=0; j<triecont; j++)
{
for(int k=0; k<(1<<m); k++)
{
if(dp[1-i%2][j][k]==0) continue;
for(int l=0; l<26; l++)
{
trie *p=node[j]->next[l];
int tep=p->mark|k;
dp[i%2][p->id][tep]+=dp[1-i%2][j][k];
if(dp[i%2][p->id][tep]>=mod) dp[i%2][j][tep]%=mod;
}
}
}
}
__int64 ans=0;
for(int i=0; i<triecont; i++)
{
for(int j=0; j<(1<<m); j++)
{
if(judge(j)>=num)
{
ans+=dp[n%2][i][j];
if(ans>=mod) ans%=mod;
}
}
}
printf("%I64d\n",ans%mod);
}
return 0;
}

[AC自己主动机+状压dp] hdu 2825 Wireless Password的更多相关文章

  1. 【AC自动机】【状压dp】hdu2825 Wireless Password

    f(i,j,S)表示当前字符串总长度为i,dp到AC自动机第j个结点,单词集合为S时的方案数. 要注意有点卡常数,注意代码里的注释. #include<cstdio> #include&l ...

  2. poj 1699 Best Sequence(AC自己主动机+如压力DP)

    id=1699" target="_blank" style="">题目链接:poj 1699 Best Sequence 题目大意:给定N个D ...

  3. hdu 4057 AC自己主动机+状态压缩dp

    http://acm.hdu.edu.cn/showproblem.php?pid=4057 Problem Description Dr. X is a biologist, who likes r ...

  4. HDU 2825 Wireless Password (AC自己主动机,DP)

    pid=2825">http://acm.hdu.edu.cn/showproblem.php? pid=2825 Wireless Password Time Limit: 2000 ...

  5. HDU - 2825 Wireless Password(AC自己主动机+DP)

    Description Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless ne ...

  6. ACM-ICPC2018南京网络赛 AC Challenge(一维状压dp)

    AC Challenge 30.04% 1000ms 128536K   Dlsj is competing in a contest with n (0 < n \le 20)n(0<n ...

  7. hdu3247Resource Archiver (AC自动机+最短路+状压dp)

    Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submis ...

  8. HDU2825 Wireless Password 【AC自动机】【状压DP】

    HDU2825 Wireless Password Problem Description Liyuan lives in a old apartment. One day, he suddenly ...

  9. HDU 2825 Wireless Password(AC自动机 + 状压DP)题解

    题意:m个密码串,问你长度为n的至少含有k个不同密码串的密码有几个 思路:状压一下,在build的时候处理fail的时候要用 | 把所有的后缀都加上. 代码: #include<cmath> ...

随机推荐

  1. tengine + lua 实现流量拷贝

    环境搭建参考地址:http://www.cnblogs.com/cp-miao/p/7505910.html cp.lua local res1, res2, action action = ngx. ...

  2. linux使用其它用户 su - op -c

    su - op -c "whoami"

  3. git rebase、git merge、git cherry-pick 使用详解

    1.git cherry-pick 是合入其他分支的某一次或者几次提交(cherry-pick是挑选的意思):把其他分支的某些功能合入当前分支 2.git merge 把其他分支合入当前分支,一般用作 ...

  4. Druid对比Vertica

    怎么比较Druid和Vertica? Vertica 类似与之前介绍的ParAccel/Redshift(Druid-vs-Redshift). 不是实时注入数据: 提供SQL的全部语法支持 另外一个 ...

  5. MapReduce初学习

    内容来源,工具下载:点此链接  点此链接 Mapreduce概述: MapReduce是一种分布式计算模型,主要用于搜索领域,解决海量数据的计算问题.MR是由两个阶段组成,Map和Reduce,用户只 ...

  6. 解决Linux关闭终端(关闭SSH等)后运行的程序或者服务自动停止【后台运行程序】

    问题描述:当SSH远程连接到服务器上,然后运行一个服务 ./catalina.sh start,然后把终端开闭(切断SSH连接)之后,发现该服务中断,导致网页无法访问.   解决方法:使用nohup命 ...

  7. 深入浅出 消息队列 ActiveMQ (转)

    启动成功就可以访问管理员界面:http://localhost:8161/admin,默认用户名和密码admin/admin.如果你想修改用户名和密码的话,在conf/jetty-realm.prop ...

  8. Idea 代码编辑错误不飘红提示

    Power Save Mode 勾选去掉即可

  9. 除了cPickle,cjson外还有没有更高效点的序列化库了

    除了cPickle,cjson外还有没有更高效点的序列化库了 http://blog.csdn.net/chen_lovelotus/article/details/7228745 msgpack最快 ...

  10. MPTCP 源码分析(三) 子路径选择

    简述:      支持MPTCP的链路中存在多条子路径,因此在发送数据的时候需要选择最优路径来进行操作. MPTCP利用内核通知链对MPTCP中各子路径进行增加路径.删除路径.修改路径优先级的操作.M ...