HDOJ 2243 考研路茫茫——单词情结 AC自动机+矩阵快速求幂和

来源:互联网 发布:岂可得乎 编辑:程序博客网 时间:2024/05/16 06:15
#include <iostream>#include <stdio.h>#include <string.h>#include <queue>using namespace std;int n,l,sz;int ch[40][26],f[40],last[40],value[40];long long map[40][40];void insert (char c[]){    int i = 0;    int len = strlen(c);    for(int j = 0; j < len; j++){        int index = c[j]-'a';        if(!ch[i][index]){            memset(ch[sz], 0, sizeof(ch[sz]));            ch[i][index] = sz;            sz++;        }        i = ch[i][index];    }    value[i] = 1;}void fail (){    queue<int> q;    for(int i = 0; i < 26; i++){        if(ch[0][i]) {f[ch[0][i]] = 0; q.push(ch[0][i]);}    }    while (!q.empty()) {        int u = q.front();        q.pop();        for(int i = 0; i < 26; i++){            if (ch[u][i]) {                int x = ch[u][i];                int y = f[u];                while(y && !ch[y][i]) y = f[y];                f[x] = ch[y][i];                last[x] = (value[f[x]]==1 ? f[x] : last[f[x]]);                q.push(x);            }        }    }}void init (){    sz = 1;    memset(ch[0], 0, sizeof(ch[0]));    memset(f, 0, sizeof(f));    memset(last, 0, sizeof(last));    memset(value, 0, sizeof(value));    memset(map, 0, sizeof(map));    for(int i = 0; i < n; i++){        char c[6];        scanf("%s", c);        insert(c);    }    fail();}void makemap (){    for(int i = 0; i < sz; i++){        if (value[i]==1) {            continue;        }        for(int j = 0; j < 26; j++){            int u = i;            while (u && !ch[u][j]) u = f[u];            u = ch[u][j];            int p = (value[u]==1 ? u : last[u]);//            while(p){//                if(value[p]==1) break;//                p = f[p];//            }            if(p==0) map[i][u]++;        }    }}void add (long long a[][40], long long b[][40]){    for(int i = 0; i < sz; i++){        for(int j = 0; j < sz; j++){            a[i][j] += b[i][j];        }    }}void mul(long long a[][40], long long b[][40]){    long long temp[40][40];    for(int i = 0; i < sz; i++){        for(int j = 0; j < sz; j++) {            temp[i][j] = 0;            for(int k = 0; k < sz; k++) temp[i][j] += a[i][k]*b[k][j];        }    }    memcpy(a, temp, sizeof(map));}void pow (long long a[][40], long long b[][40], int k){    memset(a, 0, sizeof(map));    for(int i = 0; i < sz; i++) a[i][i] = 1;    long long mm[40][40];    memcpy(mm,b,sizeof(map));    while (k) {        if (k%2==1) {            mul(a, mm);        }        mul(mm, mm);        k = k/2;    }}void pow_sum (long long a[][40], long long b[][40], int k){    if (k==1) {        memcpy(a, b, sizeof(map));        return;    }    long long c[40][40];    long long d[40][40];    memset(a, 0, sizeof(map));    pow_sum(a, b, k>>1);    pow(c, b, k>>1);    memcpy(d, a, sizeof(map));    mul(d, c);    add(a, d);    if (k%2==1) {        mul(c, c);        mul(c, b);        add(a, c);    }}int main(int argc, const char * argv[]){    while (scanf("%d%d",&n,&l)!=EOF) {        init();        makemap();        long long result[40][40];        pow_sum(result, map, l);        long long ret = 0;        for(int i =0; i < sz; i++) ret -= result[0][i];        map[0][0] = 26;        sz = 1;        pow_sum(result, map, l);        ret += result[0][0];        printf("%I64u\n",ret);        //printf("%lld\n",ret);    }}

0 0
原创粉丝点击