[AC自动机+状压dp] hdu 2825 Wireless Password
来源:互联网 发布:迅雷 mac 老版本 编辑:程序博客网 时间:2024/05/06 04:10
题意:
给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 20090717using 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;}
0 0
- hdu 2825 Wireless Password 【ac自动机+dp】
- HDU 2825 Wireless Password【AC自动机+DP】
- hdu 2825 Wireless Password(ac自动机&dp)
- 【HDU】2825 Wireless Password AC自动机+DP
- HDU - 2825 Wireless Password(AC自动机+DP)
- HDU 2825 Wireless Password (AC自动机,DP)
- HDU 2825 Wireless Password(AC自动机+状压DP)
- HDU 2825 Wireless Password && AC自动机+状压DP
- hdu 2825 Wireless Password(AC自动机+状压DP)
- [AC自动机+状压dp] hdu 2825 Wireless Password
- hdu 2825 Wireless Password(AC自动机+状压DP)
- hdu 2825 Wireless Password (ac自动机+状压dp)
- HDU 2825(Wireless Password-AC自动机+状压dp)
- HDU 2825-Wireless Password(AC自动机+状压DP)
- HDU 2825 Wireless Password (AC自动机 + 状压dp)
- hdu 2825 Wireless Password AC自动机+状态压缩DP
- HDU 2825 Wireless Password(AC自动机+状态压缩DP)
- HDU 2825 Wireless Password AC自动机 + 状态压缩DP
- Cocos2d-X中Menu的综合运用
- C语言内存分布(BSS段、数据段、代码段、堆与栈)
- 你属于几K(千)?
- Mac安装mosquitto 使用brew安装后没有mosquitto命令可以执行
- UVA 10118 - Free Candies
- [AC自动机+状压dp] hdu 2825 Wireless Password
- 整理MAC下Eclipse的常用快捷键
- JAVA的类,对象 继承 接口的认识与实践
- 知识点总结(补充版)
- 抓了小老虎 药价会降吗?
- ubuntu12.04 创建sublime text2 桌面图标
- Listview 中 getChildAt方法记录
- 使用比较运算符号进行比较查询
- 第八周项目三——多分段函数求值(switch语句)