HDU2825 Wireless Password(AC自动机+状压DP)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU2825 Wireless Password(AC自动机+状压DP)相关的知识,希望对你有一定的参考价值。
题目问长度n至少包含k个咒语的字符串有多少个。也是比较入门的题。。
- dp[i][j][S]表示长度i(在自动机上转移k步)且后缀状态为自动机上第j个结点且当前包含咒语集合为S的方案数
- dp[0][0][0]=1
- 还是用我为人人转移,AC自动机上的结点要多一个域表示这个结点所代表咒语前缀包含的咒语集合。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 int tn,ch[111][26],fail[111],flag[111]; 6 void insert(char *s,int k){ 7 int x=0; 8 for(int i=0; s[i]; ++i){ 9 int y=s[i]-‘a‘; 10 if(ch[x][y]==0) ch[x][y]=++tn; 11 x=ch[x][y]; 12 } 13 flag[x]|=1<<k; 14 } 15 void init(){ 16 memset(fail,0,sizeof(fail)); 17 queue<int> que; 18 for(int i=0; i<26; ++i){ 19 if(ch[0][i]) que.push(ch[0][i]); 20 } 21 while(!que.empty()){ 22 int x=que.front(); que.pop(); 23 for(int i=0; i<26; ++i){ 24 if(ch[x][i]) que.push(ch[x][i]),fail[ch[x][i]]=ch[fail[x]][i]; 25 else ch[x][i]=ch[fail[x]][i]; 26 flag[ch[x][i]]|=flag[ch[fail[x]][i]]; 27 } 28 } 29 } 30 int getCnt(int s){ 31 int res=0; 32 for(int i=0; i<10; ++i){ 33 if((s>>i)&1) ++res; 34 } 35 return res; 36 } 37 int d[26][111][1<<10]; 38 int main(){ 39 char str[11]; 40 int n,m,k; 41 while(~scanf("%d%d%d",&n,&m,&k) && (n||m||k)){ 42 tn=0; 43 memset(ch,0,sizeof(ch)); 44 memset(flag,0,sizeof(flag)); 45 for(int i=0; i<m; ++i){ 46 scanf("%s",str); 47 insert(str,i); 48 } 49 init(); 50 memset(d,0,sizeof(d)); 51 d[0][0][0]=1; 52 for(int i=0; i<n; ++i){ 53 for(int j=0; j<=tn; ++j){ 54 for(int k=0; k<(1<<m); ++k){ 55 if(d[i][j][k]==0) continue; 56 for(int y=0; y<26; ++y){ 57 d[i+1][ch[j][y]][k|flag[ch[j][y]]]+=d[i][j][k]; 58 d[i+1][ch[j][y]][k|flag[ch[j][y]]]%=20090717; 59 } 60 } 61 } 62 } 63 int res=0; 64 for(int i=0; i<=tn; ++i){ 65 for(int j=0; j<(1<<m); ++j){ 66 if(getCnt(j)<k) continue; 67 res+=d[n][i][j]; 68 res%=20090717; 69 } 70 } 71 printf("%d\n",res); 72 } 73 return 0; 74 }
以上是关于HDU2825 Wireless Password(AC自动机+状压DP)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 2825 Wireless Password(AC自动机)
HDU2825 Wireless Password(AC自动机+状压DP)
HDU 2825 Wireless Password AC自动机+dp