http://acm.split.hdu.edu.cn/showproblem.php?pid=2243
题意: 这题跟POJ 2778大体思路一样,只不过2778是找出不含有病毒串的,而这道题是找出含有病毒串的数量,那么我们只要找到不含病毒串的数量有多少个之后再用总数相减就好。但要记得这个题用的是邻接矩阵求出不满足的条件,之后再用矩阵存储
{26,1}
{0, 1} 这样的矩阵进行矩阵快速幂之后我们得到的a[0][1]这个值就是 26^1+26^2+26^3+…….+26^4…….得到的值之后减去不含病毒串的值就行
#include <cmath>
#include <queue>
#include <cstdio>
#include <string.h>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define LL unsigned __int64
#define INF 0x3f3f3f3f
#define MME(i,j) memset(i,j,sizeof(i))
using namespace std;
const int maxn = 15;
const int mod = 1e5;
int m;char str[15];
int limted;
__int64 k;
struct matrix{LL a[111][111];}X;
matrix operator * (matrix a,matrix b)
{
matrix c;
MME(c.a,0);
for(int i=0; i<limted; i++)
for(int j=0; j<limted; j++) //实现矩阵乘法
{
for(int k=0; k<limted; k++)
{
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]);
}
}
return c;
}
matrix operator ^ (matrix a,LL b)
{
matrix c;
MME(c.a,0);
for(long long i=0;i<limted;i++)
c.a[i][i]=1;
while(b)
{
if(b & 1) c= c * a ;
b >>= 1;
a = a * a ;
}
return c;
}
/*int ch(char c)
{
if(c=='A') return 0;if(c=='C') return 1;
if(c=='G') return 2;if(c=='T') return 3;
}*/
struct Trie
{
int next[111][27],fail[111],end[111];
int root,L;
int newnode()
{
for(int i = 0;i < 26;i++)
next[L][i] = -1;
end[L++] = 0;
return L-1;
}
// init right********
void init(){L = 0;root = newnode();}
void insert(char buf[])
{
int id,len = strlen(buf);
int now = root;
for(int i = 0;i < len;i++)
{
id=buf[i]-'a';
if(next[now][id] == -1)
next[now][id] = newnode();
now = next[now][id];
}
end[now]=1;
}
// insert right **************
// build right **************
void build()
{
queue<int>Q;
fail[root] = root;
for(int i = 0;i < 26;i++)
if(next[root][i] == -1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while( !Q.empty() )
{
int now = Q.front();
Q.pop();
if(end[fail[now]])
end[now]=1;
for(int i = 0;i < 26;i++)
if(next[now][i] == -1)
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]]=next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}ac;
matrix getmatrix(matrix A)
{
MME(A.a,0);
for(int i=0;i<ac.L;i++)
for(int j=0;j<26;j++)
if( !ac.end[ac.next[i][j]] )
A.a[i][ac.next[i][j]]++;
//这里 不一样
for(int i=0;i<=ac.L;i++)
A.a[i][ac.L]=1;
return A;
}
LL fun(LL x,LL n)
{
LL res=1;
while(n>0)
{
if(n & 1)
res=(res*x);
x=(x*x);
n >>= 1;
}
return res;
}
int main()
{
int i;
while(~scanf("%d%I64d",&m,&k))
{
ac.init();
for(i=1;i<=m;i++)
{
scanf("%s",str);
ac.insert(str);
}
ac.build();
limted=ac.L+1;
X = getmatrix(X);
X=X^k;
//right
// *******************
LL ans = 0;
for(i=0;i<=ac.L;i++) ans = (ans + X.a[0][i]);
//这里 不懂
X.a[0][0]=26;X.a[0][1]=X.a[1][1]=1;X.a[1][0]=0;
limted=2;
X=X^(k+1);//
ans=X.a[0][1]-ans;
printf("%I64u\n",ans);
}
return 0;
}