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

    http://acm.hdu.edu.cn/showproblem.php?pid=2243

    题意:

    给出m个模式串,求长度不超过n的且至少包含一个模式串的字符串个数。

    思路:

    如果做过poj2778的话,那么这题相对来说就会容易一些。

    如果直接去计算的话,情况很复杂,和poj2778一样,我们先求出不包含模式串的个数,最后只需要相减就可以。

    因为这道题目长度只要不超过n就可以,所以在构造矩阵的时候需要多加一列,该列值每行全设为1(这样最后一列的值就是对上一个矩阵每一行的和,完美计算了了各种长度的个数之和)。最后得到的值res-1就是不包含的情况个数(减去1是因为一开始的时候多算了1)。

    接下来计算一下所有情况的个数,$f(n)=1+26^1+26^2+...+26^n$,可以得出$f(n)=26*f(n-1)+1$,于是这就能构造出一个矩阵了,最后得到的res-1就是所有的情况个数。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 #include<set>
     11 using namespace std;
     12 typedef long long ll;
     13 const int INF = 0x3f3f3f3f;
     14 const int maxn=10000+5;
     15 
     16 int n, m, num;
     17 char s[20];
     18 
     19 struct Trie
     20 {
     21     int son[30];
     22     int cnt;
     23     int fail;
     24 }t[100];
     25 
     26 struct Matrix
     27 {
     28     unsigned long long mat[40][40], n;
     29     Matrix(){}
     30     Matrix(int _n)
     31     {
     32         n=_n;
     33         for(int i=0;i<n;i++)
     34         for(int j=0;j<n;j++)
     35             mat[i][j]=0;
     36     }
     37     Matrix operator*(const Matrix& b) const
     38     {
     39         Matrix c=Matrix(n);
     40         for(int i=0;i<n;i++)
     41         {
     42             for(int j=0;j<n;j++)
     43             {
     44                 for(int k=0;k<n;k++)
     45                 {
     46                     c.mat[i][j]+=mat[i][k]*b.mat[k][j];
     47                 }
     48             }
     49         }
     50         return c;
     51     }
     52 };
     53 
     54 void init(int x)
     55 {
     56     t[x].fail=0;
     57     t[x].cnt=0;
     58     memset(t[x].son,0,sizeof(t[x].son));
     59 }
     60 
     61 void trie(char *s)
     62 {
     63     int n=strlen(s);
     64     int x=0;
     65     for(int i=0;i<n;i++)
     66     {
     67         int c=s[i]-'a'+1;
     68         if(!t[x].son[c])
     69         {
     70             num++;
     71             init(num);
     72             t[x].son[c]=num;
     73         }
     74         x=t[x].son[c];
     75     }
     76     t[x].cnt=1;
     77 }
     78 
     79 void buildAC()
     80 {
     81     queue<int> Q;
     82     for(int i=1;i<=26;i++)  if(t[0].son[i])  Q.push(t[0].son[i]);
     83     while(!Q.empty())
     84     {
     85         int x=Q.front(); Q.pop();
     86         int fail=t[x].fail;
     87         for(int i=1;i<=26;i++)
     88         {
     89 
     90             int y=t[x].son[i];
     91             if(y)
     92             {
     93                 t[y].fail=t[fail].son[i];
     94                 t[y].cnt|=t[t[fail].son[i]].cnt;  //这儿很重要,这个标记需要传递
     95                 Q.push(y);
     96             }
     97             else t[x].son[i]=t[fail].son[i];
     98         }
     99     }
    100 }
    101 
    102 Matrix getMatrix()
    103 {
    104     Matrix c=Matrix(num+2);
    105     for(int i=0;i<=num;i++)
    106     {
    107         for(int j=1;j<=26;j++)
    108         {
    109             if(t[t[i].son[j]].cnt==0)  c.mat[i][t[i].son[j]]++;
    110         }
    111     }
    112     for(int i=0; i<num+2; i++)  c.mat[i][num+1]=1;
    113     return c;
    114 }
    115 
    116 
    117 Matrix q_pow(Matrix base, int n)
    118 {
    119     Matrix ans=Matrix(base.n);
    120     for(int i=0;i<ans.n;i++)   ans.mat[i][i]=1;
    121     while(n)
    122     {
    123         if(n&1)  ans=ans*base;
    124         base=base*base;
    125         n>>=1;
    126     }
    127     return ans;
    128 }
    129 
    130 int main()
    131 {
    132     //freopen("in.txt","r",stdin);
    133     while(~scanf("%d%d",&m,&n))
    134     {
    135         init(0);
    136         num=0;
    137         for(int i=1;i<=m;i++)
    138         {
    139             scanf("%s",s);
    140             trie(s);
    141         }
    142         buildAC();
    143         Matrix c=getMatrix();
    144         c = q_pow(c,n);
    145         unsigned long long res = 0;
    146         for(int i=0;i<c.n;i++) res+=c.mat[0][i];
    147         res--;
    148         c=Matrix(2);
    149         c.mat[0][0]=26;
    150         c.mat[0][1]=c.mat[1][1]=1;
    151         c=q_pow(c,n);
    152         unsigned long long ans=c.mat[0][0]+c.mat[0][1];
    153         ans--;
    154         ans-=res;
    155         cout<<ans<<endl;
    156     }
    157     return 0;
    158 }
  • 相关阅读:
    [WP8.1UI控件编程]SemanticZoom控件实现分组列表
    [深入浅出WP8.1(Runtime)]Toast通知
    [深入浅出WP8.1(Runtime)]生成图片和存储生成的图片文件
    [深入浅出WP8.1(Runtime)]应用文件的URI方案
    [深入浅出WP8.1(Runtime)]浮出控件(Flyout)
    [深入浅出WP8.1(Runtime)]文本框(TextBox)
    [深入浅出WP8.1(Runtime)]文本块(TextBlock)
    [深入浅出WP8.1(Runtime)]Windows Phone 8.1和Silverlight 8.1的区别
    [WP8.1UI控件编程]Windows Phone XAML页面的编译
    [WP8.1UI控件编程]Windows Phone大数据量网络图片列表的异步加载和内存优化
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7439949.html
Copyright © 2011-2022 走看看