zoukankan      html  css  js  c++  java
  • HDU2243_考研路茫茫――单词情结

    给出一些词根,问你有多少种长度为L的串包含至少一个词根。

    去年就在敲这个题了,今年才敲出来,还是内牛满面之中。。。

    要求包含至少一个的情况,需要求出所有的情况,减去一个都没有的情况就可以了。

    对于给出的词根,上自动机。然后我们根据tire图可以得出关系状态转移的矩阵。

    显然就是矩阵求和了,通过二分幂解决即可。这些地方都有一些技巧可言的。

    一开始没有考虑压缩fail指针,考虑了非法的情况,真是wa出翔了。

     

     

    召唤代码君:

     

     

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    typedef unsigned long long ll;
    using namespace std;
    
    ll n,L;
    ll next[55][26],fail[55],tag[55],N;
    
    struct Mat{
        ll a[55][55];
        Mat() { memset(a,0,sizeof a); }
        Mat operator + (Mat M) const {
            Mat tmp;
            for (ll i=0; i<=n; i++)
                for (ll j=0; j<=n; j++) tmp.a[i][j]=a[i][j]+M.a[i][j];
            return tmp;
        }
        Mat operator * (Mat M) const {
            Mat tmp;
            for (ll i=0; i<=n; i++)
                for (ll j=0; j<=n; j++) 
                    for (ll k=0; k<=n; k++)
                        tmp.a[i][j]+=a[i][k]*M.a[k][j];
            return tmp;
        }
        Mat power(ll x)
        {
            Mat tmp1,tmp2;
            for (ll i=0; i<=n; i++){
                tmp1.a[i][i]=1;
                for (ll j=0; j<=n; j++){
                    tmp2.a[i][j]=a[i][j];
                }
            }
            while (x){
                if (x&1) tmp1=tmp1*tmp2;
                x>>=1,tmp2=tmp2*tmp2;
            }
            return tmp1;
        }
        void output(){
            for (ll i=0; i<=n; i++){
                for (ll j=0; j<=n; j++) cout<<a[i][j]<<' ';
                cout<<endl;
            }
        }
    };
    
    ll add()
    {
        fail[++N]=0,tag[N]=0;
        for (ll i=0; i<26; i++) next[N][i]=0;
        return N;
    }
    
    void insert(char s[])
    {
        ll cur=0,k;
        for (ll i=0; s[i]; i++){
            k=s[i]-'a';
            if (!next[cur][k]) next[cur][k]=add();
            cur=next[cur][k];
        }
        tag[cur]=1;
    }
    
    void AC_build()
    {
        queue<int> Q;
        Q.push(0);
        while (!Q.empty()){
            ll cur=Q.front(),child,k;
            Q.pop();
            for (ll i=0; i<26; i++){
                child=next[cur][i];
                if (child){
                    if (!cur) fail[child]=0;
                        else{
                            for (k=fail[cur]; k && !next[k][i]; k=fail[k]) ;
                            fail[child]=next[k][i];
                        }
                    Q.push(child);
                }
                else next[cur][i]=next[fail[cur]][i];
            }
        }
    }
    
    ll power(ll x,ll y)
    {
        ll tot=1;
        while (y){
            if (y&1) tot=tot*x;
            y>>=1,x=x*x;
        }
        return tot;
    }
    
    int main()
    {
        char s[55];
        while (cin>>n>>L){
            N=0;
            fail[0]=tag[0]=0;
            for (ll i=0; i<26; i++) next[0][i]=0;
            for (ll i=0; i<n; i++)
            {
                scanf("%s",s);
                insert(s);
            }
            AC_build();
            for (ll i=0; i<=N; i++)
                if (tag[fail[i]]) tag[i]=1;
            n=N;
            Mat cur,E,ans;
            for (ll i=0; i<=n; i++)
                for (ll j=0; j<26; j++){
                    if (!tag[i] && !tag[next[i][j]]) cur.a[i][next[i][j]]++;
                }
                
            for (ll i=0; i<=n; i++) E.a[i][i]=1;
            Mat tmp=E;
            ll num=0,here=1;
            while (L>0){
                if (L&1) {
                    ans=ans+tmp*cur.power(L);
                    num+=here*power(26,L);
                }
                L>>=1;
                here=here*power(26,L)+here;
                tmp=tmp*(cur.power(L)+E);
            }
            for(ll i=0; i<=n; i++) num-=ans.a[0][i];
            cout<<num<<endl;
        }
        return 0;
    }
  • 相关阅读:
    简明git教程(单人版本) 阿星小栈
    Laravel SQL 查询语句集锦 阿星小栈
    PHP生成唯一订单号 阿星小栈
    php根据ID生成员工编号 阿星小栈
    laravel框架获取当前url 的方法 阿星小栈
    Laravel 通过Url确定返回错误信息格式 阿星小栈
    电脑用js调用QQ 聊天 阿星小栈
    js 设置cookie和获取cookie 阿星小栈
    php + ajax异步上传文件 阿星小栈
    MISCONF Redis is configured to save RDB snapshots, but it is currently not able to... 阿星小栈
  • 原文地址:https://www.cnblogs.com/lochan/p/3870736.html
Copyright © 2011-2022 走看看