代码改变世界

DNA Sequence

2019-12-04 21:44  一只弱鸡丶  阅读(256)  评论(0编辑  收藏  举报

题目链接:

四种状态A T C G,对于每个病毒串插入时的最后一个字符标记为1,表示该串不能出现!(trie字典树)

建立fail数组,对于没有出现的状态都归于0状态,建立AC自动机fail指针时顺带记录当前串的后缀是否是病毒

所有东西处理完之后根据每个串的状态去建邻接矩阵

之后就是我们最喜欢的矩阵快速幂了

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
#define ll long long
#define re register
const int N=1e6+10;
const int mod=1e5;
void read(int &a)
{
    a=0;int d=1;char ch;
    while(ch=getchar(),ch>'9'||ch<'0')
        if(ch=='-')
            d=-1;
    a=ch^48;
    while(ch=getchar(),ch>='0'&&ch<='9')
        a=(a<<3)+(a<<1)+(ch^48);
    a*=d;
}
struct note{int nex,to[5],bz;}trie[N];
char s[N];
struct node{int a[105][105];}ans,a;
int cnt=0;
map <char,int> vis;
void init(){vis['A']=0;vis['C']=1;vis['G']=2;vis['T']=3;}
void ins()
{
    int len=strlen(s),now=0;
    for(re int i=0;i<len;i++)
    {
        int x=vis[s[i]];
        if(!trie[now].to[x]) trie[now].to[x]=++cnt;
        now=trie[now].to[x];
    }
    trie[now].bz=1;
}
void build()
{
    queue <int> q;
    for(re int i=0;i<4;i++) if(trie[0].to[i]) trie[trie[0].to[i]].nex=0,q.push(trie[0].to[i]);
    while(!q.empty())
    {
        int p=q.front();q.pop();
        for(re int i=0;i<4;i++)
        {
            if(trie[p].to[i]) q.push(trie[p].to[i]),trie[trie[p].to[i]].nex=trie[trie[p].nex].to[i];
            else trie[p].to[i]=trie[trie[p].nex].to[i];
            trie[trie[p].to[i]].bz|=trie[trie[trie[p].nex].to[i]].bz;
        }
    }
}
void built()
{
    for(re int i=0;i<=cnt;i++)
        for(re int j=0;j<4;j++)
            if(!trie[i].bz&&!trie[trie[i].to[j]].bz)
                a.a[i][trie[i].to[j]]++;
}
node mul(node x,node y)
{
    node c;
    for(re int i=0;i<=cnt;i++)
    {
        for(re int j=0;j<=cnt;j++)
        {
            c.a[i][j]=0;
            for(re int k=0;k<=cnt;k++)
                c.a[i][j]=(c.a[i][j]+1ll*x.a[i][k]*y.a[k][j]%mod)%mod;
        }
    }
    return c;
}
node quickmod(node x,int y)
{
    node res,base=x;
    for(re int i=0;i<=cnt;i++)
        for(re int j=0;j<=cnt;j++)
            res.a[i][j]=i==j?1:0;
    while(y)
    {
        if(y&1) res=mul(res,base);
        base=mul(base,base);
        y>>=1;
    }
    return res;
}
int main()
{
    init();
    int m,n;
    read(m),read(n);
    while(m--)
    {
        scanf("%s",&s);
        ins();
    }
    for(re int i=0;i<=cnt;i++)
        for(re int j=0;j<=cnt;j++)
            a.a[i][j]=0;
    build();built();
    ans=quickmod(a,n);
    int answer=0;
    for(re int i=0;i<=cnt;i++) answer=(answer+ans.a[0][i])%mod;
    printf("%d",answer);
    return 0;
}