zoukankan      html  css  js  c++  java
  • hdu_2243_考研路茫茫——单词情结(AC自动机+矩阵)

    题目链接:hdu_2243_考研路茫茫——单词情结

    题意:

    让你求包含这些模式串并且长度不小于L的单词种类

    题解:

    这题是poj2788的升级版,没做过的强烈建议先做那题。

    我们用poj2778的方法可以求出不包含这些单词的,然后算出全部种类数,相减就是答案

    全部种类数的公式为f[n]=1 + 26^1 + 26^2 +...26^n

    AC自动机建出来的矩阵需要在最后添加一列1,这样在矩阵快速幂的时候就能计算出从1~n的幂和

     1 #include<bits/stdc++.h>
     2 #define mst(a,b) memset(a,b,sizeof(a))
     3 #define F(i,a,b) for(int i=a;i<=b;i++)
     4 typedef unsigned long long ll;
     5 //-----------------------矩阵-------------------------
     6 const int mat_N=6*7+7;//矩阵阶数
     7 int N;
     8 struct mat{
     9     ll c[mat_N][mat_N];
    10     void init(){mst(c,0);}
    11     mat operator*(mat b){
    12         mat M;M.init();
    13         F(i,0,N)F(j,0,N)F(k,0,N)M.c[i][j]=M.c[i][j]+c[i][k]*b.c[k][j];
    14         return M;
    15     }
    16     mat operator^(ll k){
    17         mat ans,M=(*this);ans.init();
    18         F(i,0,N)ans.c[i][i]=1;
    19         while(k){if(k&1)ans=ans*M;k>>=1,M=M*M;}
    20         return ans;
    21     }
    22 }A;
    23 //-----------------------AC自动机-----------------------
    24 const int AC_N=6*8*26,tyn=26;//数量乘串长,类型数
    25 struct AC_automation{
    26     int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot;
    27     inline int getid(char x){return x-'a';}
    28     void nw(){cnt[++tot]=0;memset(tr[tot],-1,sizeof(tr[tot]));}
    29     void init(){tot=-1,fail[0]=-1,nw();}
    30     void insert(char *s,int x=0){
    31         for(int len=strlen(s),i=0,w;i<len;x=tr[x][w],i++)
    32             if(tr[x][w=getid(s[i])]==-1)nw(),tr[x][w]=tot;
    33         cnt[x]++;//串尾标记
    34     }
    35     void build(int head=1,int tail=0){
    36         for(Q[++tail]=0;head<=tail;){
    37             for(int i=0,x=Q[head++],p=-1;i<tyn;i++)if(~tr[x][i]){
    38                 if(x==0)fail[tr[0][i]]=0;
    39                 else for(p=fail[x],fail[tr[x][i]]=0;~p;p=fail[p])
    40                         if(~tr[p][i]){fail[tr[x][i]]=tr[p][i];break;}
    41                 if(cnt[fail[tr[x][i]]])cnt[tr[x][i]]=1;
    42                 Q[++tail]=tr[x][i];
    43             }else if(x==0)tr[x][i]=0;
    44             else tr[x][i]=tr[fail[x]][i];
    45         }
    46     }
    47 }AC;
    48 
    49 void build_mat()
    50 {
    51     A.init();
    52     F(i,0,AC.tot)F(j,0,25)if(!AC.cnt[i]&&!AC.cnt[AC.tr[i][j]])A.c[i][AC.tr[i][j]]++;
    53     N=AC.tot+1;
    54     F(i,0,N)A.c[i][N]=1;//矩阵添加一列1,能将矩阵从1~n的幂和算出来
    55 }
    56 
    57 ll q_pow(ll k)
    58 {
    59     unsigned long long ans=1,tp=26;
    60     while(k){if(k&1)ans*=tp;k>>=1,tp*=tp;}
    61     return ans;
    62 }
    63 
    64 ll f_ck(ll k)//计算26的从1~k的幂和
    65 {
    66     if(k==1)return 26;
    67     ll t=0;
    68     if(k&1)t=q_pow(k);
    69     return (1+q_pow(k>>1))*f_ck(k>>1)+t;
    70 }
    71 
    72 int main()
    73 {
    74     ll n,m,ans,tp;char buf[30];
    75     while(~scanf("%llu%llu",&n,&m))
    76     {
    77         AC.init();
    78         F(i,1,n)scanf("%s",buf),AC.insert(buf);
    79         AC.build(),build_mat(),A=A^m,ans=0;
    80         F(i,0,N)ans+=A.c[0][i];
    81         tp=f_ck(m);
    82         printf("%llu
    ",tp-ans+1);
    83     }
    84     return 0;
    85 }
    View Code
  • 相关阅读:
    PHP实现邮件的自动发送
    为PostgreSQL的表自动添加分区
    django
    django的logging模块
    job
    python 类的方法带的self理解
    java
    choice_set的理解
    django
    proxy_next_upstream带来的坑和加载sticky模块
  • 原文地址:https://www.cnblogs.com/bin-gege/p/5711453.html
Copyright © 2011-2022 走看看