zoukankan      html  css  js  c++  java
  • hdu 2243 考研路茫茫——单词情结(AC自动+矩阵)

    考研路茫茫——单词情结

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 4843    Accepted Submission(s): 1527


    Problem Description
    背单词,始终是复习英语的重要环节。在荒废了3年大学生涯后,Lele也终于要开始背单词了。
    一天,Lele在某本单词书上看到了一个根据词根来背单词的方法。比如"ab",放在单词前一般表示"相反,变坏,离去"等。

    于是Lele想,如果背了N个词根,那这些词根到底会不会在单词里出现呢。更确切的描述是:长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个呢?这里就不考虑单词是否有实际意义。

    比如一共有2个词根 aa 和 ab ,则可能存在104个长度不超过3的单词,分别为
    (2个) aa,ab,
    (26个)aaa,aab,aac...aaz,
    (26个)aba,abb,abc...abz,
    (25个)baa,caa,daa...zaa,
    (25个)bab,cab,dab...zab。

    这个只是很小的情况。而对于其他复杂点的情况,Lele实在是数不出来了,现在就请你帮帮他。
     
    Input
    本题目包含多组数据,请处理到文件结束。
    每组数据占两行。
    第一行有两个正整数N和L。(0<N<6,0<L<2^31)
    第二行有N个词根,每个词根仅由小写字母组成,长度不超过5。两个词根中间用一个空格分隔开。
     
    Output
    对于每组数据,请在一行里输出一共可能的单词数目。
    由于结果可能非常巨大,你只需要输出单词总数模2^64的值。
     
    Sample Input
    3
    aa ab
    1 2
    a
     
    Sample Output
    104 52
    /*
    hdu 2243 考研路茫茫——单词情结(AC自动+矩阵)
    
    给你m个子串,求包含至少一个子串的长度不大于n的字符串的种类数
    所有可能: 26+26^2 + .... + 26^n
    而且前面也求过一个子串都不包含的情况。即把他们的关系转换成矩阵mat
    一个都不包含的情况: mat + mat^2 +..... + mat^n
    对于求 次方和.  mat+... mat^6 = mat+mat^2+mat^3 + mat^3*(mat+mat^2+mat^3)
    于是求出两个的值然后减去即可
    
    // 矩阵求a走m步到b的方案数 + A + A^2 + A^3 + ... + A^k的结果(两个矩阵的经典应用)
    hhh-2016-04-23 22:33:39
    */
    #include <iostream>
    #include <vector>
    #include <cstring>
    #include <string>
    #include <cstdio>
    #include <queue>
    #include <algorithm>
    #include <functional>
    #include <map>
    using namespace std;
    #define lson  (i<<1)
    #define rson  ((i<<1)|1)
    typedef unsigned long long ll;
    typedef unsigned int ul;
    const int  maxn = 40010;
    int tot;
    
    struct Matrix
    {
        int len;
        ll ma[50][50];
        Matrix() {}
        Matrix(int L)
        {
            len = L;
        }
    };
    
    Matrix mult(Matrix ta,Matrix tb)
    {
        Matrix tc;
        tc.len = ta.len;
        for(int i = 0; i < ta.len; i++)
        {
            for(int j = 0; j < ta.len; j++)
            {
                tc.ma[i][j] = 0;
                for(int k = 0; k < ta.len; k++){
                    tc.ma[i][j] = tc.ma[i][j]+(ll)ta.ma[i][k]*tb.ma[k][j];
                }
            }
        }
        return tc;
    }
    
    Matrix pow_mat(Matrix a,ll n)
    {
        Matrix cnt;
        cnt.len = a.len;
        memset(cnt.ma,0,sizeof(cnt.ma));
        for(int i = 0 ; i < cnt.len; i++)
            cnt.ma[i][i] = 1;
    
        while(n)
        {
            if(n&1) cnt = mult(cnt,a);
            a = mult(a,a);
            n >>= 1;
        }
        return cnt;
    }
    
    Matrix Add(Matrix ta,Matrix tb)
    {
        Matrix tc;
        tc.len = ta.len;
        for(int i = 0;i < tc.len;i++)
        {
            for(int j = 0;j < tc.len;j++)
            {
                tc.ma[i][j] = (ta.ma[i][j]+tb.ma[i][j]);
            }
        }
        return tc;
    }
    
    struct Tire
    {
        int nex[50][26],fail[50],ed[50];
        int root,L;
        int newnode()
        {
            for(int i = 0; i < 26; i++)
                nex[L][i] = -1;
            ed[L++] = 0;
            return L-1;
        }
    
        void ini()
        {
            L = 0,root = newnode();
        }
    
        void inser(char buf[])
        {
            int len = strlen(buf);
            int now = root;
            for(int i = 0; i < len; i++)
            {
                int ta = buf[i]-'a';
                if(nex[now][ta] == -1)
                    nex[now][ta] = newnode();
                now = nex[now][ta];
            }
            ed[now]  ++;
        }
    
        void build()
        {
            queue<int >q;
            fail[root] = root;
            for(int i = 0; i < 26; i++)
                if(nex[root][i] == -1)
                    nex[root][i] = root;
                else
                {
                    fail[nex[root][i]] = root;
                    q.push(nex[root][i]);
                }
            while(!q.empty())
            {
                int now = q.front();
                q.pop();
                if(ed[fail[now]])
                    ed[now] = 1;
                for(int i = 0; i < 26; i++)
                {
                    if(nex[now][i] == -1)
                        nex[now][i] = nex[fail[now]][i];
                    else
                    {
                        fail[nex[now][i]] = nex[fail[now]][i];
                        q.push(nex[now][i]);
                    }
                }
            }
        }
    
        Matrix to_mat()
        {
            Matrix mat(L);
            memset(mat.ma,0,sizeof(mat.ma));
            for(int i = 0;i < L;i++)
            {
                for(int j = 0;j < 26;j++)
                {
                    if(!ed[nex[i][j]])
                        mat.ma[i][nex[i][j]] ++;
                }
            }
            return mat;
        }
    };
    
    
    
    Matrix mat;
    
    Matrix cal(int n)
    {
        if(n == 1)
            return mat;
        Matrix tp = cal(n/2);
        if(n & 1)
        {
            Matrix t = pow_mat(mat,n/2+1);
            tp = Add(tp,mult(t,tp));
            tp = Add(tp,t);
        }
        else
        {
            Matrix t = pow_mat(mat,n/2);
            tp = Add(tp,mult(t,tp));
        }
        return tp;
    }
    
    ll pow_mod(ll a,int n)
    {
        ll cnt = 1;
        while(n)
        {
            if(n&1) cnt = cnt*a;
            a = a*a;
            n >>= 1;
        }
        return cnt;
    }
    
    ll ca(int n)
    {
        if(n == 1)
            return 26;
        ll tp = ca(n/2);
        if(n & 1)
        {
            ll t = pow_mod(26,n/2+1);
            tp = tp+t+tp*t;
        }
        else
        {
           ll t = pow_mod(26,n/2);
           tp = tp+t*tp;
        }
        return tp;
    }
    
    Tire ac;
    char buf[20];
    int main()
    {
        int n,m;
        while(scanf("%d%d",&m,&n) != EOF)
        {
            ac.ini();
            for(int i = 1; i <= m; i++)
            {
                scanf("%s",buf);
                ac.inser(buf);
            }
            ac.build();
            mat = ac.to_mat();
            Matrix ans = cal(n);
            ll tans = ca(n);
            ll t = 0;
            for(int i = 0;i < ans.len;i++)
            {
                t += ans.ma[0][i];
            }
            printf("%I64u
    ",tans-t);
        }
        return 0;
    }
    

      

  • 相关阅读:
    满屏的宽高纯CSS布局
    截屏上传插件开发流程
    COM ACTIVEX 中的BSTR 类型与其它类型转换
    线程中访问控件
    OOP三言两语
    通过iframe上传
    历年作品点评
    每周进度及工作量统计2016090820160915
    英文词频统计的java实现方法
    四人小组项目——连连看
  • 原文地址:https://www.cnblogs.com/Przz/p/5449301.html
Copyright © 2011-2022 走看看