zoukankan      html  css  js  c++  java
  • hdu_2825_Wireless Password(AC自动机+状压DP)

    题目链接:hdu_2825_Wireless Password

    题意:

    给你m个串,问长度为n至少含k个串的字符串有多少个

    题解:

    设dp[i][j][k]表示考虑到长度为i,第j个自动机的节点,含有k这个压缩状态的方案数,然后DP下去就行了

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;i++)
     3 using namespace std;
     4 
     5 const int mod=20090717;
     6 const int AC_N=10*51,tyn=26;//数量乘串长,类型数
     7 struct AC_automation{
     8     int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot;
     9     inline int getid(char x){return x-'a';}
    10     void nw(){cnt[++tot]=0,fail[tot]=0;memset(tr[tot],0,sizeof(tr[tot]));}
    11     void init(){tot=-1,fail[0]=-1,nw();}
    12     void insert(char *s,int ids,int x=0){
    13         for(int len=strlen(s),i=0,w;i<len;x=tr[x][w],i++)
    14             if(!tr[x][w=getid(s[i])])nw(),tr[x][w]=tot;
    15         cnt[x]|=1<<ids;//串尾标记
    16     }
    17     void build(int head=1,int tail=0){
    18         for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i];
    19         while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++)
    20             if(tr[x][i])fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i],cnt[tr[x][i]]|=cnt[tr[fail[x]][i]];
    21             else tr[x][i]=tr[fail[x]][i];
    22     }
    23 }AC;
    24 
    25 char s[111];
    26 int dp[26][111][1<<11],n,m,k,ans;
    27 
    28 inline int getans(int s,int an=0)
    29 {
    30     F(i,0,9)if((s>>i)&1)an++;
    31     return an;
    32 }
    33 
    34 int main()
    35 {
    36     while(~scanf("%d%d%d",&n,&m,&k)&&(n||m||k))
    37     {
    38         AC.init(),ans=0;
    39         F(i,0,m-1)scanf("%s",s),AC.insert(s,i);
    40         AC.build();
    41         memset(dp,0,sizeof(dp)),dp[0][0][0]=1;
    42         F(i,0,n-1)F(j,0,AC.tot)for(int k=0;k<(1<<m);++k)
    43         if(dp[i][j][k]!=0)F(ii,0,25)
    44         {
    45             int *p=&dp[i+1][AC.tr[j][ii]][k|AC.cnt[AC.tr[j][ii]]];
    46             *p=(*p+dp[i][j][k])%mod;
    47         }
    48         F(i,0,AC.tot)for(int j=0;j<(1<<m);j++)if(getans(j)>=k)ans=(ans+dp[n][i][j])%mod;
    49         printf("%d
    ",ans);
    50     }
    51     return 0;
    52 }
    View Code
  • 相关阅读:
    线程安全好文章
    分布式事务
    jvm内存泄漏问题分析过程
    Java8--Lambda表达式
    ZK Watcher 的原理和实现
    JVM垃圾回收算法
    linux常用命令
    Excel常用函数汇总
    Debian 镜像使用帮助
    photon 下载地址
  • 原文地址:https://www.cnblogs.com/bin-gege/p/5818585.html
Copyright © 2011-2022 走看看