http://www.cppblog.com/menjitianya/archive/2014/07/10/207604.html
上面的网站介绍了字典树、失配指针、Trie图,讲的很清晰
题意:给你n个串,求一个长度为m的不包含给定串的串的个数需要的知识点:知道AC自动机和Trie图、矩阵快速幂、m[i][j] = x表示i到j结点有长度为1的路有x条,那么m的n次幂c[][]就表示i到j结点长度为n的路有c[i][j]
思路分析:最重要的一步就是求Trie图,通过Trie图确定结点之间的路径条数,然后它的m次幂就表示长度为m的路径条数,答案就是从0结点出发到任意结点的长度为n的路径个数之和
这里在提醒下:poj上G++的运行速度比C++快
代码如下:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define N 105
#define MOD 100000
#define inf 0x7ffffff
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
int f[N];
int getnum(char c)
{
switch(c)
{
case 'A':return 0;
case 'T':return 1;
case 'C':return 2;
case 'G':return 3;
}
}
struct Matrix
{
int m[N][N];
Matrix(){
memset(m,0,sizeof(m));
}
}I;
void get_I()
{
int i,j;
memset(I.m,0,sizeof(I.m));
for(i = 0; i < N; i++)
for(j = 0; j < N; j++)
if(i == j) I.m[i][j] = 1;
}
struct node
{
int ch[N][5];
int val[N];
int sz;
void init()
{
sz = 1;
memset(ch,0,sizeof(ch));
memset(val,0,sizeof(val));
memset(f,0,sizeof(f));
}
void insert(char *str)
{
int len = strlen(str);
int i, u = 0;
for(i = 0; i < len; i++)
{
int c = getnum(str[i]);
if(ch[u][c] == 0)
ch[u][c] = sz++;
u = ch[u][c];
}
val[u] = 1;
}
void GetFail()//构建fail指针,利用fail指针建立Trie图
{
queue<int> q;
f[0] = 0;
int i;
for(i = 0; i < 4; i++)
{
int u = ch[0][i];
if(u == 0)
ch[0][i] = 0;
else{
q.push(u);
f[u] = 0;
}
}
while(!q.empty())
{
int u = q.front();
q.pop();
if(val[f[u]])
val[u] = 1;
for(i = 0; i < 4; i++)
{
int v = ch[u][i];
if(v == 0)
ch[u][i] = ch[f[u]][i];
else{
q.push(v);
f[v] = ch[f[u]][i];
}
}
}
}
Matrix get_matrix()
{
int i,j;
Matrix a;
for(i = 0; i < sz; i++)
for(j = 0; j < 4; j++)
{
int u = ch[i][j];
if(val[u] == 0)
a.m[i][u]++;
}
return a;
}
}Trie;
Matrix matrixmul(Matrix a,Matrix b,int n)
{
int i,j,k;
Matrix c;
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
for(k = 0; k < n; k++)
c.m[i][j] = (c.m[i][j] + ((long long)a.m[i][k]*b.m[k][j])%MOD)%MOD;
return c;
}
Matrix matrixpow(Matrix a,int n,int k)
{
Matrix c = a;
Matrix b = I;
while(n)
{
if(n&1)
b = matrixmul(b,c,k);
n >>= 1;
c = matrixmul(c,c,k);
}
return b;
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int n,m;
get_I();
while(scanf("%d%d",&n,&m) != EOF)
{
Trie.init();
char str[20];
int i;
for(i = 0; i < n; i++)
{
scanf("%s",str);
printf("%s\n",str);
Trie.insert(str);
}
Trie.GetFail();
Matrix a;
a = Trie.get_matrix();
a = matrixpow(a,m,Trie.sz);
int ans = 0;
for(i = 0; i < Trie.sz; i++)
ans = (ans + a.m[0][i])%MOD;
printf("%d\n",ans);
}
return 0;
}