[cpp]
<pre name="code" class="cpp"><pre name="code" class="cpp">#include<cstdio>
#include<queue>
#include<cstring>
#include<cstring>
using namespace std;
typedef __int64 type;
const int kind=4; //每個節點的子節點的個數上限
const int mod = 100000;
const int size=109; //轉移矩陣的行大小
class AC_auto
{
public:
int tot;
type Mar[size][size],ans[size][size];
struct Node
{
int key,cnt;
struct Node *next[kind],*fail;
Node()
{
key=0;
for(int i=0;i<kind;i++)
next[i]=0;
}
}*root,node[size];
inline Node * new_Node()
{
Node *p=&node[tot]; //靜態方式,可以改為動態方式 new Node()
p->cnt=tot;
p->key=0; //表示本節點是不是單詞的結尾
memset(p->next,0,sizeof(p->next));
tot++;
return p;
}
AC_auto(){ tot=0,root=new_Node(); }
int Index(char c)
{
switch(c)
{
case 'A':return 0;
case 'C':return 1;
case 'G':return 2;
case 'T':return 3;
}
}
void insert(char *s)//構造字典樹
{
int i=0;
Node *p=root;
while(s[i])
{
if(p->next[Index(s[i])]==0)
{
p->next[Index(s[i])]=new_Node();
}
p=p->next[Index(s[i])];
i++;
}
p->key++;
}
void build_fail()
{
root->fail=root;
queue<Node *> q;
q.push(root);
while(!q.empty())
{
Node *t=q.front();q.pop();
Node *p=0;
for(int i=0;i<kind;i++)
{
if(t->next[i]!=0)
{
if(t==root) t->next[i]->fail = root;
else
{
p=t->fail; //從父節點的失敗指針開始
while(p!=root&&p->next[i]==0) p=p->fail;//循環失敗指針,一直搜索非根節點有相同索引的節點
if(p->next[i]) t->next[i]->fail=p->next[i]; //找到,失敗指針指向它
else t->next[i]->fail=root; //無相同索引,失敗指針指向根節點
}
if(t->next[i]->fail->key!=0) t->next[i]->key++;
q.push(t->next[i]);
}
else
{
if(t==root) t->next[i]=root;//如果根節點無此索引,失敗指針指向根,表示此狀態可以轉換為根所代表的狀態
t->next[i]=t->fail->next[i];
}
}
}
}
void get_Mar()
{
memset(Mar,0,sizeof(Mar));
for(int i=0;i<tot;i++)
if(node[i].key==0)
{
for(int j=0;j<kind;j++)
{
if(node[i].next[j]->key==0)
{
Mar[i][node[i].next[j]->cnt]++;
}
}
}
}
void MatrixMultiply(type b[][size], type c[][size], int sz)//矩陣乘
{
int i,j,k;
type temp[size][size] = {0};
for (i=0; i<sz; i++)
{
for (j=0; j<sz; j++)
{
for (k=0; k<sz; k++)
{
temp[i][j] += b[i][k]*c[k][j];
if (temp[i][j]>=mod)
temp[i][j] %= mod;
}
}
}
for (i=0; i<sz; i++)
{
for (j=0; j<sz; j++)
{
b[i][j] = temp[i][j];
}
}
}
void MatrixPow(type t[][size], type a[][size], int sz, int n) //矩陣的快速冪
{
while(n>0)
{
if (n&1) MatrixMultiply(t, a, sz);
MatrixMultiply(a, a, sz);
n >>= 1;
}
}
void solve(int n)
{
memset(ans,0,sizeof(ans));
for(int i=0;i<size;i++)
ans[i][i]=1;
MatrixPow(ans,Mar,tot,n);
type res = 0;
for(int i=0; i<tot; i++)
{
if (node[i].key==0)
{
res += ans[0][i];
if (res>=mod)
res %= mod;
}
}
printf("%I64d\n",res);
}
int query(char *s)
{
int i=0,sum=0;
Node *p=root;
while(s[i])
{
while(p->next[Index(s[i])]==0&&p!=root)p=p->fail;//某個非根節點匹配失敗,一直循環失敗指針直到有某個字典樹分支可以匹配
p=(p->next[Index(s[i])]==0)?root:p->next[Index(s[i])];//一直到根也未找到滿足條件的分支,則從根開始匹配
Node *t=p;
while(t!=root&&t->key!=-1)//循環失敗指針,記錄匹配次數
{
sum+=t->key;
t->key=-1;
t=t->fail;
}
i++;
}
return sum;
}
};
char keyword[19],str[1000009];
int main()
{
int m,n;
while(scanf("%d%d",&m,&n)!=EOF)
{
AC_auto x;
while(m--)
{
scanf("%s",keyword);
x.insert(keyword);
}
x.build_fail();
x.get_Mar();
x.solve(n);
}
}
作者:wsniyufang