hdu 2243 ac自动机 dp +矩阵快速幂

来源:互联网 发布:阿里云上传自己镜像 编辑:程序博客网 时间:2024/05/21 08:40

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243

参考 :http://www.cnblogs.com/kuangbin/p/3159520.html#commentform


艰难地ac了。。。15ms

#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include<queue>using namespace std;typedef unsigned long long LL;const int SN = 26;const int MN = 40;struct Matrix{    int n;    LL v[MN][MN];    Matrix(){memset(v,0,sizeof(v));}    Matrix(int n){        this->n = n;        for(int i = 0; i < n; ++i)            for(int j = 0; j < n; ++j)                v[i][j] = 0;    }    Matrix(bool){        for(int i = 0; i < MN; ++i)            for(int j = 0; j < MN; ++j)               if(i != j) v[i][j] = 0;                else v[i][j] = 1;    }};Matrix operator *(const Matrix &a,const Matrix &b){            Matrix c;            c.n = a.n;            int N = a.n;            for(int i = 0; i < N; ++i)                for(int j = 0;j < N; ++j){                    for(int k = 0; k < N; ++k)                        c.v[i][j] += a.v[i][k]*b.v[k][j];                }            return c;}Matrix operator^(Matrix a,LL b){        Matrix c(true);        c.n = a.n;        while(b){                if(b&1uLL) c = c*a;                a = a*a;                b >>= 1;        }        return c;}LL getsumoffirstline(Matrix a){        LL sum = 0;        int N = a.n;        for(int i = 0;i < N; ++i) sum += a.v[0][i];        return sum;}class AAM{public:    int ch[MN][SN],tag[MN],fail[MN];    int root,cnt;    void init(){        cnt = 0,root = cnt++;        memset(ch[0],0,sizeof(ch[0]));        memset(tag,0,sizeof(tag));        memset(fail,0,sizeof(fail));    }    void insert(char *s){        int p = root;        while(*s){                int  index = *s - 'a';                if(tag[p]) return;//小小的优化                if(!ch[p][index]){                    ch[p][index] = cnt;                    memset(ch[cnt],0,sizeof(ch[cnt]));                    ++cnt;                }                p = ch[p][index];                s++;        }        tag[p] = 1;    }    void getfail(){            queue<int> Q;            for(int i = 0; i < SN; ++i){//两个数组都有清零不用再赋0给他了                 if(ch[0][i]){                        Q.push(ch[0][i]);                 }            }            while(!Q.empty()){                int u = Q.front();Q.pop();                if(tag[fail[u]]) tag[u] = 1;                for(int i = 0;i < SN; ++i){                    int &v = ch[u][i];                    if(v){                          fail[v] = ch[fail[u]][i];                          Q.push(v);                    }else v = ch[fail[u]][i];                }            }    }    Matrix getMatrix(){            Matrix a;            int cnt1;            for(int i = 0; i < cnt; ++i)                for(int j = 0; j < SN; ++j)                    if(!tag[i] && !tag[ch[i][j]]){                        a.v[i][ch[i][j]] ++;                    }            for(int i = 0; i < cnt; ++i){   //压缩行列                cnt1 = 0;                for(int j = 0; j < cnt; ++j){                        if(!tag[j]){                            a.v[i][cnt1++] = a.v[i][j];                        }                }            }                for(int i = 0; i < cnt; ++i){                    cnt1 = 0;                    for(int j = 0; j < cnt; ++j){                        if(!tag[j]){                            a.v[cnt1++][i] = a.v[j][i];                        }                    }                }        for(int i = 0; i <= cnt; ++i)                a.v[cnt1][i] = 0,                a.v[i][cnt1] = 1;        a.n = cnt1 + 1;        return a;    }};char s[15];LL n,L;AAM T;int main(){    while(~scanf("%I64u%I64u",&n,&L)){    T.init();    while(n--){        scanf("%s",s);        T.insert(s);    }    T.getfail();    Matrix a = T.getMatrix();    a = a^L;    LL sum = getsumoffirstline(a);    a = Matrix(2);    a.v[0][0] = 26; a.v[0][1] = 0; a.v[1][0] = 1;a.v[1][1] = 1;    a = a^L;// 1 + 26 + 26^2 +... 26^L    sum = a.v[0][0] + a.v[1][0] - sum;    printf("%I64u\n",sum);    }    return 0;}


0 0
原创粉丝点击