基本上是跟着kuangbin挂的题和模板做的,渣渣都不好意思膜。。。
理解的AC自动机,在一个大串里找挺多小串,把小串构成trie树,根节点root 为 0,每个节点有一个序号,node[i][j]中i表示序号为i的点, j表示下一个字符为j,node[i][j]表示这个节点的序号
fail函数表示失配后跳转到哪,在整个trie树中跳转,用BFS一层一层计算,跟KMP一样
hdu2222就是纯模板,
query的时候也跟KMP一样,ed记录节点是否为某个串的结尾,注意把ed[t] 变为0,某个串出现过多次也计算为一次,有些题需要修改
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
#define ll long long
#define FOR(i,j,k) for(int i =j; i<=k ;i++)
#define ll long long
const int maxn =500010;
int node[maxn][26],fail[maxn],ed[maxn];
char s[1000010];
struct trie
{
int root ,L;//L表示节点总数
int newnode()
{
FOR(i , 0,25)
node[L][i] = -1;
ed[L] = 0;
L++;
return L-1;
}
void init()
{
L =0;
root = newnode();
memset(ed , 0 ,sizeof(ed));
}
void insert(char s[])
{
int len = strlen(s);
int now = root ;
FOR( i , 0, len-1)
{
if(node[now][s[i] - 'a'] == -1)
node[now][s[i] - 'a'] = newnode();
now =node[now][s[i] - 'a'];
}
ed[now] ++;//ed记录当前点是几个keyword的结尾
}
void build()
{
queue<int>q;
fail[root] = root;
FOR(i, 0 ,25)
if(node[root][i] == -1)
node[root][i] = root;
else
{
fail[node[root][i]] = root;
q.push(node[root][i]);
}
while(!q.empty())
{
int now = q.front();
q.pop();
FOR(i, 0, 25)
{
if(node[now][i] == -1)
node[now][i] = node[fail[now]][i];//不存在的点的标号为失配后的点标号
else{
fail[node[now][i]] = node[fail[now]][i];
q.push(node[now][i]);
}
}
}
}
int query()
{
int len = strlen(s);
int now= root;
int ans =0;
FOR( i, 0, len -1)
{
now = node[now][s[i] - 'a'];
int t = now;
while( t!= root)
{
ans +=ed[t];
ed[t] = 0;//有些题需要修改
t = fail[t];
}
}
return ans;
}
};
trie ac;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ac.init();
int n;
scanf("%d" ,&n);
FOR( i, 1, n){
scanf("%s",s);
ac.insert(s);
}
ac.build();
scanf("%s", s);
printf("%d\n",ac.query());
}
return 0;
}
poj2778 矩阵+ac自动机
矩阵是这样构造的:用ed记录一个点是否可以转换过去,如果一个节点fail失配过去的节点是不可转换的,那它也是不可转换的
用mat[i][j]记录从节点i到节点j需要多少步
大概就这样,注意我矩阵模板的行列数。。。。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
#define ll long long
#define FOR(i,j,k) for(int i =j; i<=k ;i++)
#define ll long long
const int maxn =105;
int node[maxn][5],fail[maxn],ed[maxn];
int id['Z'+1];
char s[20];
struct mat
{
int x , y ;
ll a[maxn][maxn];
};
mat M;
mat operator *(mat & a, mat & b)
{
mat c;
memset( c.a , 0 , sizeof(c.a));
c.x = a.x;
c.y = b.y;
FOR( i, 0, a.x)
FOR( k, 0, a.y){
if( a.a[i][k] != 0 )
FOR( j, 0, b.y)
c.a[i][j] = (c.a[i][j]+ a.a[i][k] * b.a[k][j]) % 100000;
}
return c;
}
mat operator ^(mat & a , int b)
{
mat m = a;
mat c;
memset( c.a, 0, sizeof(c.a));
FOR( i, 0, a.x)
c.a[i][i] = 1;
c.x = c.y = a.x;
while(b)
{
if(b % 2 != 0)
c = c * m ;
m = m * m;//相当于二进制
b >>= 1;//矩阵快速幂要用循环写,递归会爆栈
}
return c;
}
void printfmat(mat m)
{
int x = m.x,y = m.y;
FOR(i,0,x){
FOR(j,0,y-1)
cout<<m.a[i][j]<<" ";
cout<<endl;
}
}
struct trie
{
int root ,L;//L表示节点总数
int newnode()
{
FOR(i , 0, 3)
node[L][i] = -1;
ed[L] = 0;
L++;
return L-1;
}
void init()
{
L =0;
root = newnode();
memset(ed, 0 ,sizeof(ed));
id['A'] = 0;
id['T'] = 1;
id['C'] = 2;
id['G'] = 3;
}
void insert(char s[])
{
int len = strlen(s);
int now = root ;
FOR( i , 0, len-1)
{
if(node[now][id[s[i]]] == -1)
node[now][id[s[i]]] = newnode();
now =node[now][id[s[i]]];
}
ed[now] =1;
}
void build()
{
queue<int>q;
fail[root] = root;
FOR(i, 0 ,3)
if(node[root][i] == -1)
node[root][i] = root;
else
{
fail[node[root][i]] = root;
q.push(node[root][i]);
}
while(!q.empty())
{
int now = q.front();
q.pop();
if( ed[fail[now]])
ed[now] =1;
FOR(i, 0, 3)
{
if(node[now][i] == -1)
node[now][i] = node[fail[now]][i];//不存在的点的标号为失配后的点标号
else{
fail[node[now][i]] = node[fail[now]][i];
q.push(node[now][i]);
}
}
}
}
void buildMatrix()
{
memset(M.a , 0 ,sizeof(M.a));
M.x = L-1, M.y = L-1;
FOR(i , 0 ,L-1)
FOR(j,0,3){
if(!ed[i] && !ed[node[i][j]])
M.a[i][node[i][j]]++;
}
}
};
trie ac;
int main()
{
int n,m;
cin>>n>>m;
ac.init();
FOR(i , 1, n){
scanf("%s",s);
ac.insert(s);
}
ac.build();
ac.buildMatrix();
//printfmat(M);
M = M^m;
//printfmat(M);
ll ans = 0;
FOR(i, 0,M.y )
{
ans+=M.a[0][i];
ans %= 100000;
}
printf("%d\n",ans);
return 0;
}