HDU - 2243 考研路茫茫——单词情结 ac自动机+矩阵快速幂

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

题解:这题基本跟poj2778一样,我们可以把所有的情况的个数计算出来=26^1+26^2+26^3+......+26^m。这个我们可以用矩阵快速幂,构造一个矩阵{26,0;26,1;},他的次幂只后a[1][0]位置的值就是所有情况的个位数,然后在减去不含任何给定词根的个数这里就是poj2778,也是构造矩阵,通过离散数学一个矩阵m的K次幂之后m[i][j]表示从i到j走K布有m[i][j]种方法,这样的话我们就可建立ac自动机,构建初始矩阵A,然后在求AA=A+A^2+A^3+....A^m(这个如何求可以先看下这个), 然后AA第一行的和就是不满足情况的个数。

做这题之前建议先做poj2778 poj3233

ac代码有点长,但我用的是模板以后可以照搬着用

  1 #include<bits/stdc++.h>
  2 #include<queue>
  3 #include<cstdio>
  4 #include<iomanip>
  5 #include<iostream>
  6 #include<string>
  7 #include<cstring>
  8 #include<algorithm>
  9 #define ll long long
 10 using namespace std;
 11 typedef unsigned long long ull;
 12 const ull mod=1ll<<64;
 13 const int maxn=1e5+10;
 14 const int N=6*5+10;
 15 int n,m;
 16 struct mat
 17 {
 18     int n, m;
 19     ull a[N*2][N*2];
 20     mat() {}
 21     void init(int _n, int _m)
 22     {
 23         n = _n;
 24         m = _m;
 25         for(int i = 0; i < n; i++)
 26         {
 27             for(int j = 0; j < m; j++) a[i][j] = 0;
 28         }
 29     }
 30     mat operator + (const mat &B)const
 31     {
 32         mat C;
 33         C.init(n,m);
 34         for(int i=0; i<n; i++)
 35             for(int j=0; j<m; j++)
 36                 C.a[i][j]=(a[i][j]+B.a[i][j]);
 37         return C;
 38     }
 39     mat operator*(const mat &P)const
 40     {
 41         mat ret;
 42         ret.init(n,m);
 43         for(int i = 0; i < n; i++)
 44         {
 45             for(int k = 0; k < m; k++)
 46             {
 47                 if(a[i][k])
 48                 {
 49                     for(int j = 0; j < P.m; j++)
 50                     {
 51                         ret.a[i][j] = (a[i][k] * P.a[k][j] + ret.a[i][j]) ;
 52                     }
 53                 }
 54             }
 55         }
 56         return ret;
 57     }
 58     mat operator^(const ll &P)const
 59     {
 60         ll num = P;
 61         mat ret, tmp = *this;
 62         ret.init(n,m);
 63         for(int i = 0; i < n; i++) ret.a[i][i] = 1;
 64         while(num)
 65         {
 66             if(num & 1) ret = ret * tmp;
 67             tmp = tmp * tmp;
 68             num >>= 1;
 69         }
 70         return ret;
 71     }
 72     void view()
 73     {
 74         for(int i=0;i<n;i++)
 75         {
 76             for(int j=0;j<m;j++)
 77             {
 78                 printf("%llu ",a[i][j]);
 79             }printf("\n");
 80         }
 81     }
 82 }ap,ad;
 83 struct ac_auto
 84 {
 85     int nxt[N][26],ed[N],fail[N],cn,rt;
 86     void init(){
 87         cn=0;
 88         rt=new_node();
 89     }
 90     int new_node()
 91     {
 92         memset(nxt[cn],-1,sizeof(nxt[cn]));
 93         ed[cn]=0;fail[cn]=-1;
 94         return cn++;
 95     }
 96     void insert(char *s)
 97     {
 98         int len=strlen(s);
 99         int p=rt;
100         for(int i=0;i<len;i++)
101         {
102             int x=s[i]-'a';
103             if(nxt[p][x]==-1)nxt[p][x]=new_node();
104             p=nxt[p][x];
105         }
106         ed[p]++;
107     }
108         void construct()
109             {
110                 queue<int> Q;
111                fail[0] = 0;
112                 for (int i = 0; i < 26; i++)
113                 {
114                     if (-1 != nxt[0][i])
115                     {
116                         fail[nxt[0][i]] = 0;
117                         Q.push(nxt[0][i]);
118                     }
119                     else
120                     {
121                         nxt[0][i] = 0;    //这个不能丢
122                     }
123                 }
124                 while ( !Q.empty() )
125                 {
126                     int u = Q.front();
127                     Q.pop();
128                     if (ed[fail[u]])
129                         ed[u] = true;         //这个很重要,当u的后缀是病毒,u也不能出现
130                     for (int i = 0; i < 26; i++)
131                     {
132                         int &v = nxt[u][i];
133                         if ( -1 != v )
134                         {
135                             Q.push(v);
136                             fail[v] = nxt[fail[u]][i];
137                         }
138                         else
139                         {
140                             v = nxt[fail[u]][i];
141                         }
142                     }
143                 }
144             }
145 
146     void get_mat()
147     {
148         ap.init(cn,cn+cn);
149         for(int i=0;i<cn;i++)
150         {
151             for(int j=0;j<26;j++)
152             {
153                 if(!ed[i]&&!ed[nxt[i][j]])
154                 {
155                     ap.a[i][nxt[i][j]]++;
156                 }
157             }
158         }
159         for(int i=0;i<cn;i++)
160         {
161             ap.a[i][i+cn]=1;
162         }
163     }
164     void view(int x)
165     {
166         cout<<x<<" "<<ed[x]<<" "<<fail[x]<<" "<<nxt[x][0]<<" "<<nxt[x][1]<<" "<<nxt[x][2]<<" "<<nxt[x][3]<<endl;
167         for(int i=0;i<4;i++)
168         {
169             if(nxt[x][i]!=-1)view(nxt[x][i]);
170         }
171     }
172 }ac;
173 int main()
174 {
175     char op[15];
176    // cout<<(((1ull<<63)-1)<<1)+1<<endl;
177   //  cout<<1ull-2<<endl;
178     while(~scanf("%d %d",&n,&m))
179     {
180         ull an1;
181         mat t2;
182         t2.init(2,2);
183         t2.a[0][0]=t2.a[1][0]=26;
184         t2.a[1][1]=1;
185         t2=t2^m;
186         an1=t2.a[1][0];
187         ac.init();
188         for(int i=1;i<=n;i++)
189         {
190             scanf("%s",op);
191             ac.insert(op);
192         }
193         ac.construct();
194         ac.get_mat();
195         ad.init(ac.cn*2,ac.cn*2);
196         for(int i=0;i<ac.cn;i++)
197         {
198             ad.a[i+ac.cn][i+ac.cn]=1;
199             for(int j=0;j<ac.cn;j++)
200             {
201                 ad.a[i+ac.cn][j]=ad.a[i][j]=ap.a[i][j];
202             }
203         }
204         ap=ap*(ad^(m-1));
205         for(int i=0;i<ac.cn;i++)
206         {
207             an1-=ap.a[0][i];
208         }
209         printf("%llu\n",an1);
210     }
211     return 0;
212 }

 

posted @ 2018-08-10 14:59  lhclqslove  阅读(243)  评论(0编辑  收藏  举报