考研路茫茫——单词情结 HDU - 2243 AC自动机/特征字符串构造计数/等比矩阵求和
细节都在注释里了,这条跟上一条挺像的,都是用自动机构造转移矩阵,
还是那个要点:trie图上u号节点转移到v号节点时,如果形成特征串就在矩阵的mat[u][v]+1
#include<bits/stdc++.h> #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) const int inf=0x3f3f3f3f; const int maxn=40+9; const int sigma=26; struct Matrix{ ull mat[maxn][maxn]; int n; Matrix(){}; Matrix(int n1){n=n1;for(int i=0;i<n;i++)for(int j=0;j<n;j++)mat[i][j]=0;} Matrix operator *(const Matrix&b)const{ Matrix ret=Matrix(n); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ for(int k=0;k<n;k++){ ret.mat[i][j]+=mat[i][k]*b.mat[k][j]; } //ret.mat[i][j]%=mod; } } return ret; } }; Matrix matpow(Matrix mat,int n){ Matrix ret=Matrix(mat.n); for(int i=0;i<mat.n;i++)ret.mat[i][i]=1; while(n){ if(n&1)ret=ret*mat; mat=mat*mat; n=n>>1; } return ret; } struct automata{ int ch[maxn][sigma]; int val[maxn]; int f[maxn]; int sz; int newnode(){ memset(ch[sz],0,sizeof(ch[sz])); f[sz]=val[sz]=0; return sz++; } void init(){ memset(val,0,sizeof(val)); sz=0; newnode(); } void insert(char *s,int v){ int u=0; int len=strlen(s); for(int i=0;i<len;i++){ int id=s[i]-'a';//s[i]-'a'; if(!ch[u][id])ch[u][id]=newnode(); u=ch[u][id]; } val[u]=1; } void build(){ queue<int>q; q.push(0); while(!q.empty()){ int u=q.front();q.pop(); if(val[f[u]]){ //当前字符串后缀是词根,则当前字符有词根 val[u]+=1; } for(int i=0;i<sigma;i++){ int v=ch[u][i]; if(!v)ch[u][i]=ch[f[u]][i]; else q.push(v); if(u&&v)f[v]=ch[f[u]][i]; } } } Matrix buildmat(){ Matrix ret=Matrix(sz+1); //增一维全1列可以储存矩阵该行和: //在连乘过程中所有第一行的和都加入了 //第一行最后一个格子中,手动模拟一下就懂了 for(int i=0;i<sz;i++){ for(int j=0;j<26;j++){ if(val[ch[i][j]]==0){ ret.mat[i][ch[i][j]]++; } } } for(int i=0;i<sz+1;i++){ret.mat[i][sz]=1;} return ret; } }ac; char s[20]; int main(){ int n,L; while(~scanf("%d%d",&n,&L)){ ac.init(); for(int i=0;i<n;i++){ scanf("%s",s); ac.insert(s,0); } ac.build(); Matrix a=ac.buildmat(); a=matpow(a,L); ull res=0; for(int i=0;i<a.n;i++)res+=a.mat[0][i];res--; //矩阵数值和 //f[L]=1+26^1+26^2+……+26^L //f[L]=26*f[L-1]+1 //{f[L],1}={f[L-1],1}*[26,0;1,1] //一共有f[L]-1种字符串 a=Matrix(2); a.mat[0][0]=26; a.mat[1][0]=a.mat[1][1]=1; a=matpow(a,L); ull ans=a.mat[1][0]+a.mat[0][0]; ans--; ans-=res; //printf("%ulld\n",ans); cout<<ans<<endl; } }