题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243
题意:给出m个串,问有多少不大于n的串至少包含m个串中的一个?
思路:首先求出不包含m个串的长度不大于n的串的个数,也就是对应矩阵A:S=A^1+A^2+……A^n。然后就是26+26^2+26^3+……+26^n-S。
const int mod=100000;
const int N=105;
struct node
{
int next[26],fail,flag;
void init()
{
clr(next,0);
fail=-1;
flag=0;
}
};
node a[N];
int e,n,m;
char s[N];
void insert(char s[])
{
int i,k,p=0;
for(i=0;s[i];i++)
{
k=s[i]-'a';
if(a[p].next[k]==0)
{
a[e].init();
a[p].next[k]=e++;
}
p=a[p].next[k];
}
a[p].flag=1;
}
queue<int> Q;
void build()
{
Q.push(0);
int i,j,k,p,q;
while(!Q.empty())
{
k=Q.front();
Q.pop();
for(i=0;i<26;i++)
{
if(a[k].next[i])
{
p=a[k].next[i];
q=a[k].fail;
while(q!=-1&&!a[q].next[i]) q=a[q].fail;
if(q==-1) a[p].fail=0;
else
{
a[p].fail=a[q].next[i];
a[p].flag|=a[a[p].fail].flag;
}
Q.push(p);
}
else
{
q=a[k].fail;
while(q!=-1&&!a[q].next[i]) q=a[q].fail;
if(q==-1) a[k].next[i]=0;
else a[k].next[i]=a[q].next[i];
}
}
}
}
u64 b[N][N],d[N][N];
void mul(u64 a[][N],u64 b[][N])
{
int i,j,k;
u64 c[N][N]={0};
FOR0(k,e) FOR0(i,e) FOR0(j,e)
{
c[i][j]+=a[i][k]*b[k][j];
}
FOR0(i,e) FOR0(j,e) b[i][j]=c[i][j];
}
u64 getPow(u64 a,u64 b)
{
u64 ans=1;
while(b)
{
if(b&1) ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}
void copyMatrix(u64 A[][N],u64 B[][N])
{
int i,j;
FOR0(i,e) FOR0(j,e) B[i][j]=A[i][j];
}
u64 getSum(u64 a,u64 n)
{
if(n==0) return 1;
if(n&1) return getSum(a,n>>1)*(1+getPow(a,n/2+1));
else return getPow(a,n)+getSum(a,n/2-1)*(1+getPow(a,n/2));
}
void initMatrix(u64 A[][N])
{
int i,j;
FOR0(i,e) FOR0(j,e) A[i][j]=0;
FOR0(i,e) A[i][i]=1;
}
void getPOW(u64 A[][N],u64 B[][N],int n)
{
initMatrix(B);
u64 C[N][N];
copyMatrix(A,C);
while(n)
{
if(n&1) mul(C,B);
mul(C,C);
n>>=1;
}
}
void addMatrix(u64 A[][N],u64 B[][N])
{
int i,j;
FOR0(i,e) FOR0(j,e) B[i][j]+=A[i][j];
}
void print(u64 A[][N])
{
int i,j;
FOR0(i,e)
{
FOR0(j,e) printf("%I64u ",A[i][j]);
puts("");
}
puts("");
}
u64 C[N][N],D[N][N],E[N][N];
void getSum(u64 A[][N],u64 B[][N],int n)
{
if(n==0)
{
initMatrix(B);
return;
}
if(n&1)
{
getSum(A,B,n/2);
initMatrix(C);
getPOW(A,D,n/2+1);
addMatrix(C,D);
mul(D,B);
}
else
{
getSum(A,B,n/2-1);
getPOW(A,C,n);
initMatrix(D);
getPOW(A,E,n/2);
addMatrix(D,E);
mul(E,B);
addMatrix(C,B);
}
}
int main()
{
while(scanf("%d%d",&m,&n)!=-1)
{
a[0].init();e=1;
int i,j,k;
FOR0(i,m) RD(s),insert(s);
build();
clr(b,0);
FOR0(i,e) if(!a[i].flag) FOR0(j,26)
{
k=a[i].next[j];
if(!a[k].flag) b[i][k]++;
}
u64 sum=getSum(26,n),x=((u64)1)<<63;;
getSum(b,d,n);
FOR0(i,e) if(!a[i].flag) sum-=d[0][i];
printf("%I64u\n",sum);
}
return 0;
}