poj2778(AC自动机+矩阵快速幂)

来源:互联网 发布:mac论坛 编辑:程序博客网 时间:2024/05/18 00:06

http://www.cppblog.com/menjitianya/archive/2014/07/10/207604.html

上面的网站介绍了字典树、失配指针、Trie图,讲的很清晰

题意:给你n个串,求一个长度为m的不包含给定串的串的个数
需要的知识点:知道AC自动机和Trie图、矩阵快速幂、m[i][j] = x表示i到j结点有长度为1的路有x条,那么m的n次幂c[][]就表示i到j结点长度为n的路有c[i][j]

思路分析:最重要的一步就是求Trie图,通过Trie图确定结点之间的路径条数,然后它的m次幂就表示长度为m的路径条数,答案就是从0结点出发到任意结点的长度为n的路径个数之和

这里在提醒下:poj上G++的运行速度比C++快

代码如下:

#include<iostream>#include<algorithm>#include<cstring>#include<string>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#include<math.h>#define N 105#define MOD 100000#define inf 0x7ffffff#define eps 1e-9#define pi acos(-1.0)using namespace std;int f[N];int getnum(char c){    switch(c)    {        case 'A':return 0;        case 'T':return 1;        case 'C':return 2;        case 'G':return 3;    }}struct Matrix{    int m[N][N];    Matrix(){        memset(m,0,sizeof(m));    }}I;void get_I(){    int i,j;    memset(I.m,0,sizeof(I.m));    for(i = 0; i < N; i++)        for(j = 0; j < N; j++)            if(i == j)  I.m[i][j] = 1;}struct node{    int ch[N][5];    int val[N];    int sz;    void init()    {        sz = 1;        memset(ch,0,sizeof(ch));        memset(val,0,sizeof(val));        memset(f,0,sizeof(f));    }    void insert(char *str)    {        int len = strlen(str);        int i, u = 0;        for(i = 0; i < len; i++)        {            int c = getnum(str[i]);            if(ch[u][c] == 0)                ch[u][c] = sz++;            u = ch[u][c];        }        val[u] = 1;    }    void GetFail()//构建fail指针,利用fail指针建立Trie图    {        queue<int> q;        f[0] = 0;        int i;        for(i = 0; i < 4; i++)        {            int u = ch[0][i];            if(u == 0)                ch[0][i] = 0;            else{                q.push(u);                f[u] = 0;            }        }        while(!q.empty())        {            int u = q.front();            q.pop();            if(val[f[u]])                val[u] = 1;            for(i = 0; i < 4; i++)            {                int v = ch[u][i];                if(v == 0)                    ch[u][i] = ch[f[u]][i];                else{                    q.push(v);                    f[v] = ch[f[u]][i];                }            }        }    }    Matrix get_matrix()    {        int i,j;        Matrix a;        for(i = 0; i < sz; i++)            for(j = 0; j < 4; j++)            {                int u = ch[i][j];                if(val[u] == 0)                    a.m[i][u]++;            }        return a;    }}Trie;Matrix matrixmul(Matrix a,Matrix b,int n){    int i,j,k;    Matrix c;    for(i = 0; i < n; i++)        for(j = 0; j < n; j++)            for(k = 0; k < n; k++)                c.m[i][j] = (c.m[i][j] + ((long long)a.m[i][k]*b.m[k][j])%MOD)%MOD;    return c;}Matrix matrixpow(Matrix a,int n,int k){     Matrix c = a;     Matrix b = I;     while(n)     {         if(n&1)            b = matrixmul(b,c,k);         n >>= 1;         c = matrixmul(c,c,k);     }     return b;}int main(){//freopen("input.txt","r",stdin);//freopen("output.txt","w",stdout);    int n,m;    get_I();    while(scanf("%d%d",&n,&m) != EOF)    {         Trie.init();         char str[20];         int i;         for(i = 0; i < n; i++)         {             scanf("%s",str);             printf("%s\n",str);             Trie.insert(str);         }         Trie.GetFail();         Matrix a;         a = Trie.get_matrix();         a = matrixpow(a,m,Trie.sz);         int ans = 0;         for(i = 0; i < Trie.sz; i++)            ans = (ans + a.m[0][i])%MOD;         printf("%d\n",ans);    }    return 0;}


0 0