习题: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+矩阵)

POJ2778DNA Sequence(AC自动机)

poj 2778 DNA Sequence ac自动机+矩阵快速幂

POJ 2778 DNA Sequence (AC自动机,矩阵乘法)

POJ 2778 DNA Sequence —— (AC自动机+矩阵快速幂)