hdu-2243(AC自动机+矩阵快速幂)
题意:给你n个字符串,和长度m,问你长度<=m的字符串中,包括这n个字符串的有多少个
解题思路:这题和poj2778差不多,但是那道题求的是不包含的,所有我们换个角度,求出所有的可能性减去不包括的就是了,但这道题有一个和那道题不一样的地方就是,他是<=长度len的所有,所有需要构造矩阵的时候加一列全为1的元素,然后求所有可能性也需要这样,构造一个2x2的矩阵【26 1 0 1】的矩阵,因为是对2^64取模,所以直接开unsigned long long 就行了
代码
#include<algorithm> #include<cstring> #include<cstdio> #include<iostream> #include<queue> using namespace std; typedef unsigned long long ll; const int N=50; const int maxn=110; ll m; int tot,n,cnt; int fail[N]; int trie[N][26]; int visit[N]; char t[10]; struct Matrix { ll m[maxn][maxn]; Matrix() { memset(m,0,sizeof(m)); } void init() { for(int i=0; i<=cnt; i++) for(int j=0; j<=cnt; j++) m[i][j]=(i==j); } Matrix operator +(const Matrix &b)const { Matrix c; for(int i=0; i<=cnt; i++) { for(int j=0; j<=cnt; j++) { c.m[i][j]=(m[i][j]+b.m[i][j]); } } return c; } Matrix operator *(const Matrix &b)const { Matrix c; for(int i=0; i<=cnt; i++) { for(int j=0; j<=cnt; j++) { for(int k=0; k<=cnt; k++) { c.m[i][j]=(c.m[i][j]+(m[i][k]*b.m[k][j])); } } } return c; } Matrix operator^(const ll &t)const { Matrix ans,a=(*this); ans.init(); ll n=t; while(n) { if(n&1) ans=ans*a; a=a*a; n>>=1; } return ans; } }; void build_trie(char *str) { int root=0; int slen=strlen(str); for(int i=0;i<slen;i++) { int id=str[i]-'a'; if(!trie[root][id]) trie[root][id]=++tot; root=trie[root][id]; } visit[root]=1; } void build_fail() { queue<int>q; for(int i=0;i<26;i++) if(trie[0][i]!=0) q.push(trie[0][i]); while(!q.empty()) { int now=q.front();q.pop(); if(visit[fail[now]]) visit[now]=1; for(int i=0;i<26;i++) { if(!trie[now][i]) { trie[now][i]=trie[fail[now]][i]; continue; } fail[trie[now][i]]=trie[fail[now]][i]; q.push(trie[now][i]); } } } void init() { memset(trie,0,sizeof(trie)); memset(fail,0,sizeof(fail)); memset(visit,0,sizeof(visit)); tot=0; } int main() { while(scanf("%d%u",&n,&m)!=EOF) { Matrix a,b;init(); for(int i=1;i<=n;i++) { scanf("%s",t);build_trie(t); } build_fail(); for(int i=0;i<=tot;i++) { if(visit[i])continue; for(int j=0;j<26;j++) { if(visit[trie[i][j]])continue; a.m[i][trie[i][j]]++; } } for(int i=0;i<=tot+1;i++) a.m[i][tot+1]=1; cnt=tot+1; a=a^m; ll ans=0; for(int i=0;i<=cnt;i++) ans+=a.m[0][i]; cnt=2; b.m[0][0]=26;b.m[0][1]=1;b.m[1][1]=1; b=b^m; ll tmp=b.m[0][0]+b.m[0][1]; cout<<tmp-ans<<endl; } }