poj 2778 AC自动机+矩阵乘法

来源:互联网 发布:ping 域名ip 编辑:程序博客网 时间:2024/05/21 11:12

首先利用病毒串建立tire图,没个节点代表某种后缀,然后利用AC自动机对各个后缀进行转移,得到一个矩阵,然后利用快速幂求解矩阵连乘。

#include<stdio.h>#include<algorithm>#include<string.h>#include<iostream>using namespace std;const int nMax=105;const int S_NUM=4;const int N_NUM=105;const int M=100000;struct Tree{    int index,flag;    Tree *fail,*next[S_NUM];}t[nMax],*Q[nMax];struct Mat{long long mat[N_NUM][N_NUM];int n,m;void init(int r,int c){n=r;m=c;}void init_e(){for(int i=0;i<n;i++)for(int j=0;j<m;j++)mat[i][j]=(i==j);}};int cnt,L,C;long long a[N_NUM][N_NUM];char key[20];Tree *root;int get(char c){   if(c=='A') return 0;   else if(c=='G') return 1;   else if(c=='C') return 2;   else return 3;}Tree* new_node(){    Tree *p=&t[cnt];    p->index=cnt++;    p->flag=0;    memset(p->next,0,sizeof(p->next));    return p;}void insert(char s[]){    Tree *p=root;    for(int i=0;s[i];i++)    {        int index=get(s[i]);        if(p->next[index]==NULL)            p->next[index]=new_node();        p=p->next[index];    }    p->flag=1;}void build_ac(){    int f=0,r=-1;    Q[++r]=root;    while(f<=r)    {        Tree *p=Q[f++];        for(int i=0;i<S_NUM;i++)        {            if(p->next[i]!=NULL)            {                if(p==root) p->next[i]->fail=root;                else                {                    p->next[i]->fail=p->fail->next[i];                    if(p->fail->next[i]->flag!=0)                        p->next[i]->flag=1;                }                Q[++r]=p->next[i];            }            else            {                if(p==root) p->next[i]=root;                else p->next[i]=p->fail->next[i];            }            if(p->next[i]->flag==0) a[p->index][p->next[i]->index]++;        }    }}Mat Mul(Mat a,Mat b){Mat ret;ret.init(a.n,b.m);memset(ret.mat,0,sizeof(ret.mat));for(int i=0;i<a.n;i++)for(int j=0;j<b.m;j++)for(int k=0;k<b.n;k++){ret.mat[i][j]+=a.mat[i][k]*b.mat[k][j];if(ret.mat[i][j]>M) ret.mat[i][j]%=M;}return ret;}Mat exp(Mat a,int k){Mat ret=a,tmp=a;ret.init_e();for(;k;k>>=1){if(k&1){ret=Mul(ret,tmp);}tmp=Mul(tmp,tmp);}return ret;}int main(){//    freopen("test.txt","r",stdin);    scanf("%d%d",&L,&C);    cnt=0;root=new_node();    for(int i=0;i<L;i++)    {        scanf("%s",key);        insert(key);    }    build_ac();    Mat b; b.init(cnt,cnt);    memcpy(b.mat,a,sizeof(a));    Mat ans=exp(b,C);    int res=0;    for(int i=0;i<cnt;i++)        res=(res+ans.mat[0][i])%M;    printf("%d\n",res);    return 0;}


 

原创粉丝点击