HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)

来源:互联网 发布:goto是java关键字吗 编辑:程序博客网 时间:2024/05/16 02:11

思路:本题和POJ2778几乎是一样的,所以可以借鉴那一道题的思路。首先求出长度不超过n的不包含任何词根的单词数,然后用总的单词数减去这种情况即可。




#include<cstdio>#include<cstring>#include<string>#include<cctype>#include<iostream>#include<set>#include<map>#include<cmath>#include<sstream>#include<vector>#include<stack>#include<queue>#include<algorithm>#define fin freopen("a.txt","r",stdin)#define fout freopen("a.txt","w",stdout)typedef long long LL;typedef unsigned long long ULL;using namespace std;const int inf = 1e9 + 10;const int maxnode = 35;const int sigma_size = 26;const int maxn = 35;char T[maxn], s[4010];char *p;struct Matrix{    int r, c;    ULL a[maxn][maxn];    void init(int r, int c, ULL x) {       this->r = r;       this->c = c;       for(int i = 1; i <= r; i++)        for(int j = 1; j <= c; j++)           a[i][j] = x;    }    };Matrix E;Matrix operator + (const Matrix &A, const Matrix &B){    int r = A.r, c = A.c;    Matrix C; C.init(r, c, 0);    for(int i = 1; i <= r; i++)      for(int j = 1; j <= c; j++)         C.a[i][j] = A.a[i][j] + B.a[i][j];    return C;}Matrix operator * (const Matrix &A, const Matrix &B){    int r = A.r, c = B.c;    Matrix C; C.init(r, c, 0);    for(int i = 1; i <= r; i++)      for(int j = 1; j <= c; j++)        for(int k = 1; k <= B.r; k++)           C.a[i][j] = A.a[i][k] * B.a[k][j] + C.a[i][j];    return C;}Matrix Pow(Matrix A, LL p){    Matrix res = E;    while(p)    {        if(p & 1) res = res * A;        p >>= 1;        A = A * A;    }    return res;}ULL Pow(ULL a, LL p){if(!p) return 1;ULL ans = Pow(a, p/2);ans *= ans;if(p & 1) ans *= a;return ans;}struct AC{    int ch[maxnode][sigma_size];    int val[maxnode];    int f[maxnode];    int sz;    int idx(char c) { return c - 'a'; }    void init()    {        memset(ch[0], 0, sizeof ch[0]);        sz = 1;        memset(val,0,sizeof val);    }    void insert(char *s)    {        int n = strlen(s), u = 0;        for(int i = 0; i < n; i++)        {            int c = idx(s[i]);            if(!ch[u][c])            {                memset(ch[sz], 0, sizeof ch[sz]);                val[sz] = 0;                ch[u][c] = sz++;            }            u = ch[u][c];        }        val[u] = 1;    }    int getFail()    {    queue<int> q;    f[0] = 0;    for(int c = 0; c < sigma_size; c++)    {    int u = ch[0][c];    if(u) { f[u] = 0; q.push(u); }    }    while(!q.empty())    {    int r = q.front(); q.pop();    for(int c = 0; c < sigma_size; c++)    {    int u = ch[r][c];    if(!u) { ch[r][c] = ch[f[r]][c]; continue; }    q.push(u);    int v = f[r];    while(v && !ch[v][c]) v = f[v];    f[u] = ch[v][c];    val[u] |= val[f[u]];    }    }    return 0;    }    Matrix getMatrix()    {    Matrix A;        A.init(sz, sz, 0);        E.init(sz, sz, 0);        for(int i = 1; i <= sz; i++) E.a[i][i] = 1;        for(int i = 0; i < sz; i++)           for(int j = 0; j < sigma_size; j++)           {              int u = i, v = ch[i][j];              if(!val[v]) ++A.a[u+1][v+1];           }         return A;    }}ac;ULL Sigma(ULL a, LL p){if(p == 0) return 1;if(p == 1) return a;LL ans = Sigma(a, p/2);ans = (ULL(1) + Pow(a, p/2)) * ans;if(p & 1) ans += Pow(a, p);return ans;}Matrix Sigma(Matrix A, LL p){if(p == 1) return A;if(p == 0) return E;Matrix Ans = Sigma(A, p/2);Ans = (E + Pow(A, p/2)) * Ans;if(p & 1) Ans = Ans + Pow(A, p);return Ans;}int main(){    int n; ULL l;    char s[100];    while(cin >> n >> l)    {    ac.init();    for(int i = 1; i <= n; i++)    {    scanf("%s", s);    ac.insert(s);    }    ac.getFail();    Matrix A = ac.getMatrix();    A = Sigma(A, l);    ULL ans = Sigma(26, l);    for(int i = 1; i <= ac.sz; i++)    {    ans -= A.a[1][i];    }    cout << ans << endl;    }    return 0;}


阅读全文
0 0