poj 2778 (AC自动机+dp+矩阵快速幂)

来源:互联网 发布:手机版晒密软件 编辑:程序博客网 时间:2024/05/17 03:59

断断续续看了一周AC自动机和Trie图,总算明白一些了,A的不易啊

/* * ===================================================================================== * *       Filename:  2778.cpp *        Version:  1.0 *        Created:  2013-08-25 00:26:31 *       Revision:  none *       Compiler:  GNU C++ * *      Just like you,wait you forever~~ * * ===================================================================================== */#include <set>#include <map>#include <list>#include <queue>#include <stack>#include <cmath>#include <string>#include <cstdio>#include <vector>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define PB              push_back#define SIZE(x)         (int)x.size()#define clr(x,y)        memset(x,y,sizeof(x))#define MP(x,y)         make_pair(x,y)#define RS(n)           scanf ("%s", n)#define ALL(t)          (t).begin(),(t).end()#define FOR(i,n,m)      for (int i = n; i <= m; i ++)#define ROF(i,n,m)      for (int i = n; i >= m; i --)#define IT              iterator#define FF              first#define SS              secondtypedef long long               ll;typedef unsigned int            uint;typedef unsigned long long      ull;typedef vector<int>             vint;typedef vector<string>          vstring;typedef pair<int, int>          PII;void RI (int& x){        x = 0;        char c = getchar ();        while (c == ' '||c == '\n')     c = getchar ();        bool flag = 1;        if (c == '-'){                flag = 0;                c = getchar ();        }        while (c >= '0' && c <= '9'){                x = x * 10 + c - '0';                c = getchar ();        }        if (!flag)      x = -x;}void RII (int& x, int& y){RI (x), RI (y);}void RIII (int& x, int& y, int& z){RI (x), RI (y), RI (z);}/**************************************END define***************************************/const ll mod = 100000;const ll LINF = 1e18;const int INF = 1e9;const double EPS = 1e-8;const int NODE = 105;const int CHD = 4;int code[255];int chd[NODE][4], sz, fail[NODE], val[NODE];void init (){        sz = 1;        clr (chd[0], 0);}void insert (char* s){        int len = strlen (s);        int p = 0;        FOR (i, 0, len-1){                int c = code[s[i]];                if (!chd[p][c]){                        clr (chd[sz], 0);                        chd[p][c] = sz ++;                }                p = chd[p][c];        }        val[p] = 1;}void getfail (){        queue<int> q;        FOR (i, 0, CHD-1){                fail[chd[0][i]] = 0;                if (chd[0][i]){                        q.push (chd[0][i]);                }        }        while (SIZE (q)){                int node = q.front ();                q.pop ();                FOR (i, 0, CHD-1){                        if (chd[node][i]){                                int tmp = fail[node];                                fail[chd[node][i]] = chd[tmp][i];                                val[chd[node][i]] += val[chd[tmp][i]];                                q.push (chd[node][i]);                        }else{                                chd[node][i] = chd[fail[node]][i];                        }                }        }}struct Mat{        ll a[105][105];        void initzero (){                clr (a, 0);        }        void initunit (){                FOR (i, 0, sz-1){                        FOR (j, 0, sz-1){                                a[i][j] = (i == j ? 1:0);                        }                }        }        void modul (){                FOR (i, 0, sz-1){                        FOR (j, 0, sz-1){                                a[i][j] %= mod;                        }                }        }        friend Mat operator * (Mat a, Mat b){                Mat ans;                ans.initzero ();                FOR (i, 0, sz-1){                        FOR (j, 0, sz-1){                                if (a.a[i][j]){                                        FOR (k, 0, sz-1){                                                ans.a[i][k] += a.a[i][j] * b.a[j][k];                                        }                                }                        }                }                ans.modul ();                return ans;        }        friend Mat operator ^ (Mat a, int n){                Mat ans;                ans.initunit ();                while (n){                        if (n&1){                                ans = ans*a;                        }                        a = a*a;                        n >>= 1;                }                return ans;        }}a;int main (){        init ();        code['A'] = 0;        code['T'] = 1;        code['C'] = 2;        code['G'] = 3;        int n, len;        RII (n, len);        FOR (i, 1, n){                char s[15];                RS (s);                insert (s);        }        getfail ();        FOR (i, 0, sz-1){                if (!val[i]){                        FOR (j, 0, CHD-1){                                int v = chd[i][j];                                if (!val[v]){                                        a.a[v][i] ++;                                }                        }                }        }        a = a^len;        ll ans = 0;        FOR (i, 0, sz-1){                ans = (ans + a.a[i][0]) % mod;        }        cout << ans << endl;}


原创粉丝点击