习题:DNA Sequence(AC自动机)
Posted loney-s
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了习题:DNA Sequence(AC自动机)相关的知识,希望对你有一定的参考价值。
题目
思路
算是AC自动机的一个经典的应用
不包含其中的任何一个字串,也就是不能再自动机上面进行匹配
只要在自动机上走的路径不包含任何一个终结节点就行了
按照常规做法,建矩阵跑快速幂
代码
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int mod=100000;
struct ac_auto
{
struct node
{
int end;
int fail;
int vis[5];
}tre[105];
struct matrix
{
int n;
long long a[105][105];
matrix(){memset(a,0,sizeof(a));}
friend matrix operator * (const matrix &a,const matrix &b)
{
matrix c;
c.n=a.n;
for(int i=0;i<=a.n;i++)
{
for(int j=0;j<=b.n;j++)
{
for(int k=0;k<=a.n;k++)
{
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
}
}
}
return c;
}
};
int cnt;
void init()
{
for(int i=0;i<=cnt;i++)
{
tre[i].end=tre[i].fail=0;
for(int j=0;j<4;j++)
tre[i].vis[j]=0;
}
cnt=0;
}
void insert(char s[])
{
int lens=strlen(s);
int now=0;
for(int i=0;i<lens;i++)
{
if(tre[now].vis[s[i]-'A']==0)
tre[now].vis[s[i]-'A']=++cnt;
now=tre[now].vis[s[i]-'A'];
}
tre[now].end=1;
}
void fail()
{
queue<int> q;
for(int i=0;i<4;i++)
{
if(tre[0].vis[i])
{
tre[tre[0].vis[i]].fail=0;
q.push(tre[0].vis[i]);
}
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<4;i++)
{
if(tre[u].vis[i])
{
tre[tre[u].vis[i]].fail=tre[tre[u].fail].vis[i];
q.push(tre[u].vis[i]);
}
else
tre[u].vis[i]=tre[tre[u].fail].vis[i];
tre[tre[u].vis[i]].end=max(tre[tre[u].vis[i]].end,tre[tre[tre[u].fail].vis[i]].end);
}
}
}
matrix qkpow(matrix a,long long b)
{
if(b==1)
return a;
matrix t=qkpow(a,b/2);
t=t*t;
if(b%2==1)
t=t*a;
return t;
}
int solve(long long n)
{
long long ans=0;
matrix ret;
matrix ini;
ret.n=cnt;
ini.n=cnt;
for(int i=0;i<=cnt;i++)
{
ini.a[i][i]=1;
if(tre[i].end)
continue;
for(int j=0;j<4;j++)
if(tre[tre[i].vis[j]].end==0)
ret.a[i][tre[i].vis[j]]++;
}
/*for(int i=0;i<=cnt;i++)
{
for(int j=0;j<=cnt;j++)
{
cout<<ret.a[i][j]<<' ';
}
cout<<'
';
}*/
ret=qkpow(ret,n);
ret=ini*ret;
/*for(int i=0;i<=cnt;i++)
{
for(int j=0;j<=cnt;j++)
{
cout<<ret.a[i][j]<<' ';
}
cout<<'
';
}*/
for(int i=0;i<=cnt;i++)
ans=(ans+ret.a[0][i])%mod;
return ans;
}
}ac;
int m;
int hashh[128];
long long n;
char s[5];
int main()
{
hashh['A']='A';
hashh['C']='B';
hashh['T']='C';
hashh['G']='D';
while(cin>>m>>n)
{
ac.init();
for(int i=1;i<=m;i++)
{
cin>>s;
for(int j=0;j<strlen(s);j++)
s[j]=hashh[s[j]];
ac.insert(s);
}
ac.fail();
cout<<ac.solve(n)<<'
';
}
return 0;
}
以上是关于习题:DNA Sequence(AC自动机)的主要内容,如果未能解决你的问题,请参考以下文章
POJ2778 DNA Sequence(AC自动机+矩阵快速幂)
POJ 2778 DNA Sequence (AC自动机+DP+矩阵)
poj 2778 DNA Sequence ac自动机+矩阵快速幂