HDU 2243 考研路茫茫——单词情结 AC自动机+DP+快速幂

来源:互联网 发布:淘宝代金券怎么使用 编辑:程序博客网 时间:2024/05/16 02:13

与此题类似

http://blog.csdn.net/viphong/article/details/53039419

dp递推一样


在它的基础上多了一步求前缀和


solution是加多一维累计即可


最后求一个26+26^2 + 26^3 + 26^4 ...的一个快速幂相减就算是答案


对2^64取模就是 ull即可


printf+ull 是%llu。。。。


#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <map>#include <set>#include <vector>#include <iostream>using namespace std;const int maxlen=200;const int maxn=6*6;const int all_size=26;int trie[maxn][all_size];int fail[maxn];int tag[maxn];int sz;queue<int >Q;const int N = 40;const long long  mod=10000000;struct Matrix{    unsigned long long mat[N][N];} ;Matrix unit_matrix ;long long n ;  int k=40;Matrix mul(Matrix a, Matrix b) //矩阵相乘{    Matrix res;    for(int i = 0; i < k; i++)        for(int j = 0; j < k; j++)        {            res.mat[i][j] = 0;            for(int t = 0; t < k; t++)            {                res.mat[i][j] += a.mat[i][t] * b.mat[t][j];               // res.mat[i][j] %= mod;            }        }    return res;}Matrix pow_matrix(Matrix a, long long m)  //矩阵快速幂{    Matrix res = unit_matrix;    while(m != 0)    {        if(m & 1)            res = mul(res, a);        a = mul(a, a);        m >>= 1;    }    return res;}struct Aho{    int root;    int newnode()//静态创建新节点    {        memset(trie[sz],-1,sizeof trie[sz]);        tag[sz]=0;        sz++;        return sz-1;    }    void init()//初始化    {        sz=0;        newnode();    }    void insert(char s[],int id)   //插入字符串构建ac自动机,构建trie树    {        int len=strlen(s),p=0;;        for (int i=0; i<len; i++)        {            int id=s[i]-'a';            if (trie[p][id]==-1)                trie[p][id]=newnode();            p=trie[p][id];        }        tag[p]=id;   //结束标记    }    void getfail() //构建自动机fail指针    {        while(!Q.empty()) Q.pop();        fail[root]=root;            //root指向root        for (int i=0; i<all_size; i++)        {            if (trie[root][i]==-1)//第一个字符不存在,指向root                trie[root][i]=root;            else    //第一个字符的fail指针指向root            {                fail[trie[root][i]]=root;                Q.push(trie[root][i]);   //并放入队列,待bfs扩展            }        }        while(!Q.empty())        {            int u=Q.front();    //取扩展节点            Q.pop();               if(tag[fail[u]])     tag[u]=1;  //***如果之前是tag,直接标记            for (int i=0; i<all_size; i++)//遍历所有子节点            {                if (trie[u][i]==-1)//如果不存在,则子节点直接指向fail[u]节点的对应子节点                    trie[u][i]=trie[fail[u]][i];                else     //如果存在,则该节点的fail指针指向fail[u]节点对应的子节点                {                    fail[trie[u][i]]=trie[fail[u]][i];                    Q.push(trie[u][i]);     //继续扩展                }            }        }    }} aho;char s[maxlen];char name[15][55];Matrix get(long long n){    k=sz+1;    Matrix c;    memset(  c.mat ,0,sizeof c.mat);    for (int i=0; i<sz; i++)    {        for (int j=0; j<26; j++)        {            if ( !tag[trie[i][j] ])            c.mat[i][trie[i][j]]++;        }    }    for (int i=0;i<=sz;i++)        c.mat[i][sz]=1;    Matrix ans = pow_matrix(c, n);  //  ans=mul(ori,ans);    return ans;}int main(){   /*  unsigned long long s=-1;    printf("%lld\n",s);*/    k=36+1;    int  i, j, t;     for(i = 0; i < k; i++)        for(j = 0; j < k; j++)            unit_matrix.mat[i][j] = 0;    for(i = 0; i < k; i++)  unit_matrix.mat[i][i] = 1;    long long  m;    while(cin>>n>>m)    {        aho.init();        for (int i=0; i<n; i++)        {            scanf("%s",name[i]);            aho.insert(name[i],i+1);        }        aho.getfail();        Matrix ret= get(m);         unsigned long long ans=0;             for (int j=0;j<=sz;j++)                ans=(ans+ret.mat[0][j]);        ans--;        Matrix c,ori;        k=2;    //    memset(  c.mat ,0,sizeof c.mat);     //   memset(  ori.mat ,0,sizeof ori.mat);        c.mat[0][0]=26;        c.mat[0][1]=0;        c.mat[1][0]=26;        c.mat[1][1]=1;        ori.mat[0][0]=0;        ori.mat[0][1]=1;        ori.mat[1][0]=0;        ori.mat[1][1]=0;        c=pow_matrix(c,m);        ori=mul(ori,c);    unsigned long long  out=ori.mat[0][0]-ans;    // cout<<out<<endl;  //AC       printf("%llu\n",out );  //WA    }    return 0;}


dp递推一样
0 0
原创粉丝点击