ZOJ 2243 考研路茫茫――單詞情結 AC自動機+矩陣快速冪
阿新 • • 發佈:2018-11-14
就是問你長度小於等於L的單詞且出現過至少一個子串的數量。首先算出長度小於等於L的單詞有多少種,26^1 + 26^2 + 26^3+ …+26^L,然後再算出長度為1,2,3…L的單詞中包含子串的數量,相減就行,第二部分用AC自動機求出矩陣,然後矩陣快速冪,其中從bin神那裡學到一個技巧,矩陣的1次+2次+3次+…L次冪的和等於在原矩陣上最右邊多加一列從0到L+1的1
#include<iostream> #include<cstring> #include<queue> using namespace std; #define LL unsigned long long const int maxnode=50; const int maxn=40; const int sigma_size=26; char s[15]; struct Node { int son[sigma_size]; int val,fail; }ch[maxnode]; struct Matrix { LL m[maxn][maxn]; Matrix() {memset(m,0,sizeof(m));} }mat,n26; int sz=1; struct AC { queue<int>Q; void init(int x) {ch[x].fail=ch[x].val=0;memset(ch[x].son,0,sizeof(ch[x].son));} int idx(char c) {return c-'a';} void insert(char s[],int v) { int u=0,n=strlen(s); for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u].son[c]) { init(sz); ch[u].son[c]=sz++; } u=ch[u].son[c]; } ch[u].val=v; } void build() { for(int i=0;i<26;i++) if(ch[0].son[i]) Q.push(ch[0].son[i]); while(!Q.empty()) { int now=Q.front();Q.pop(); int fail=ch[now].fail; for(int i=0;i<26;i++) { int nxt=ch[now].son[i]; if(nxt) { ch[nxt].fail=ch[fail].son[i]; Q.push(nxt); } else ch[now].son[i]=ch[fail].son[i]; ch[ch[now].son[i]].val|=ch[ch[ch[now].fail].son[i]].val; } } } int solve(char s[]) { int len=strlen(s),ans=0,now=0; for(int i=0;i<len;i++) { int c=idx(s[i]); while(now&&!ch[now].son[c]) now=ch[now].fail; now=ch[now].son[c]; int p=now; while(p&&ch[p].val!=-1) { ans+=ch[p].val; p=ch[p].fail; } } return ans; } void buildMatrix() { memset(mat.m,0,sizeof(mat.m)); for(int i=0;i<sz;i++) { for(int j=0;j<26;j++) { if(ch[i].val!=1&&ch[ch[i].son[j]].val!=1) { mat.m[i][ch[i].son[j]]++; } } } for(int i=0;i<sz+1;i++) mat.m[i][sz]=1; } }ans; Matrix operator*(const Matrix &m1,const Matrix &m2){ Matrix m; for(int i=0; i<=sz; ++i){ for(int j=0; j<=sz; ++j){ for(int k=0; k<=sz; ++k){ m.m[i][j]+=m1.m[i][k]*m2.m[k][j]; } } } return m; } Matrix q_pow(Matrix x,LL n) { Matrix res; for(int i=0;i<=sz;i++) res.m[i][i]=1; while(n) { if(n%2==1) res=res*x; n/=2; x=x*x; } return res; } int main() { ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); LL n,m; while(cin>>n>>m) { memset(n26.m,0,sizeof(n26.m)); n26.m[0][0]=26,n26.m[0][1]=n26.m[1][1]=1; n26=q_pow(n26,m); ans.init(0);sz=1; for(int i=1;i<=n;i++) { cin>>s; ans.insert(s,1); } ans.build(); ans.buildMatrix(); mat=q_pow(mat,m); LL res=n26.m[0][0]+n26.m[0][1]; for(int i=0;i<=sz;i++) { res=res-mat.m[0][i]; } cout<<res<<endl; } return 0; }