hdu2825(AC自动机+状态压缩dp)

链接:点击打开链接

题意:求一个长度是n的字符串至少含有给出的m个字符串中的k个的种数

代码:

#include <queue>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int MOD=20090717;
int dp[30][105][(1<<10)+5];
int fail[100005],vis[100005];
int str[100005][30],dis[100005];
int root,id;
void insert(char *s){
    int u=0;
    for(;*s;s++){
        if(!str[u][*s-'a'])
        str[u][*s-'a']=root++;
        u=str[u][*s-'a'];
    }
    dis[u]|=(1<<(id-1));                        //用二进制表示每个状态
    id++;
}
void getfail(){
    int u,v,i,temp;
    queue<int>q;
    q.push(0);
    while(q.size()){
       u=q.front();q.pop();
       for(i=0;i<26;i++){
            if(!str[u][i])
            str[u][i]=str[fail[u]][i];
            else
            {
                temp=str[u][i];
                if(u)
                fail[temp]=str[fail[u]][i];
                dis[temp]|=dis[fail[temp]];     //整合每个状态
                q.push(temp);
            }
        }
    }
}                                               // 自动机模板
int main(){                                     //dp[i][j][k]表示长度是i的串匹配到j节点状态是k的值
    int n,m,k,i,j,x,y,z,ans;
    char s[15];
    while(scanf("%d%d%d",&n,&m,&k)!=EOF&&(n||m||k)){
    root=id=1;
    memset(str,0,sizeof(str));
    memset(dis,0,sizeof(dis));
    memset(fail,0,sizeof(fail));
    for(i=0;i<m;i++){
        scanf("%s",s);
        insert(s);
    }
    getfail();
    for(x=0;x<=n;x++)
    for(y=0;y<root;y++)
    for(z=0;z<(1<<m);z++)
    dp[x][y][z]=0;
    dp[0][0][0]=1;
    for(x=0;x<n;x++)
    for(y=0;y<root;y++)
    for(z=0;z<(1<<m);z++)
    if(dp[x][y][z]){                            
        for(j=0;j<26;j++){
            dp[x+1][str[y][j]][z|dis[str[y][j]]]+=dp[x][y][z];
            dp[x+1][str[y][j]][z|dis[str[y][j]]]%=MOD;
        }
    }
    ans=0;
    for(i=0;i<(1<<m);i++)
    if(__builtin_popcount(i)>=k){               //个数不少于k    
        for(j=0;j<root;j++)
        ans=(ans+dp[n][j][i])%MOD;
    }
    printf("%d\n",ans);
    }
    return 0;
}


 

你可能感兴趣的:(源码,动态规划,ACM)