• HDU2243 考研路茫茫——单词情结 [AC自动机+矩阵]


      就是POJ2778的加强版,思路是一样的。

      出现过给定的单词的单词数=总单词数-未出现过给定单词的单词数,前者等于26^1+26^2+26^3....26^l,后者等于Mat^1+Mat^2+..Mat^l,这里的Mat是根据能走的字符之间的路径数建立出来的邻接矩阵。两者求出来一减就可以了,对2^64取模可以忽略,直接用unsigned long long做,忽视溢出就等于取模了,注意减法最后结果可能小于0,要加2^64变成正数。

      求a^1+..a^n用一次二分就可以,建议这种二分都写成非递归的,效率比较高而且不会有爆栈的隐患。

      

    #include <stdio.h>
    #include <string.h>
    #define MAXN 31
    
    typedef unsigned long long LL;
    LL dmat[MAXN][MAXN];
    struct matrix{
        LL mz[MAXN][MAXN];
        int n;
        #define FOR(i) for(int i=0;i<n;i++)
        matrix(int nn,int type):n(nn){
            if(type==0)FOR(i)FOR(j)mz[i][j]=0;
            else if(type==1)FOR(i)FOR(j)mz[i][j]=(i==j?1:0);
            else FOR(i)FOR(j)mz[i][j]=dmat[i][j];
        }
        matrix operator *(const matrix& b)const{
            matrix ans(n,0);
            FOR(i)FOR(j)if(mz[i][j])
                FOR(k)ans.mz[i][k]+=mz[i][j]*b.mz[j][k];
            return ans;
        }
        matrix operator +(const matrix& b)const{
            matrix ans(n,0);
            FOR(i)FOR(j)ans.mz[i][j]=mz[i][j]+b.mz[i][j];
            return ans;
        }
        //M^1+M^2+M^3...M^N
        matrix binPlusMul(int x){
            matrix ans(n,0),tmp(n,2),mat(n,2);
            int bit=1;
            for(LL i=(x>>1);i;i>>=1,bit<<=1);bit>>=1;
            for(ans=mat;bit;bit>>=1){
                ans=ans+tmp*ans;
                tmp=tmp*tmp;
                if(bit&x){
                    tmp=tmp*mat;
                    ans=ans+tmp;
                }
            }
            return ans;
        }
    };
    int next[MAXN][26],fail[MAXN],flag[MAXN],pos;
    int newnode(){
        for(int i=0;i<26;i++)next[pos][i]=0;
        fail[pos]=flag[pos]=0;
        return pos++;
    }
    void insert(char *s){
        int p=0;
        for(int i=0;s[i];i++){
            int k=s[i]-'a',&x=next[p][k];
            p=x?x:x=newnode();
        }
        flag[p]=1;
    }
    int q[MAXN],front,rear;
    void makenext(){
        q[front=rear=0]=0,rear++;
        while(front<rear){
            int u=q[front++];
            for(int i=0;i<26;i++){
                int v=next[u][i];
                if(flag[v])continue;
                if(v==0)next[u][i]=next[fail[u]][i];
                else q[rear++]=v;
    
                if(u&&v){
                    fail[v]=next[fail[u]][i];
                    if(flag[fail[v]])flag[v]=1;
                }
            }
        }
    }
    LL cal(int x,int n){
        int bit=1;
        LL ans=0,tmp=x;
        for(int i=(n>>1);i;i>>=1,bit<<=1);bit>>=1;
        for(ans=x;bit;bit>>=1){
            ans=ans+tmp*ans;
            tmp=tmp*tmp;
            if(bit&n){
                tmp=tmp*x;
                ans=ans+tmp;
            }
        }
        return ans;
    
    }
    int n;
    LL l;
    char s[10];
    int main(){
        //freopen("test.in","r",stdin);
        while(scanf("%d%d",&n,&l)!=EOF){
            pos=0;newnode();
            memset(dmat,0,sizeof dmat);
            for(int i=0;i<n;i++){
                scanf("%s",s);
                insert(s);
            }
            makenext();
            for(int u=0;u<pos;u++){
                if(flag[u])continue;
                for(int i=0;i<26;i++){
                    int v=next[u][i];
                    if(flag[v])continue;
                    dmat[u][v]++;
                }
            }
            matrix mt(pos,2);
            matrix mat=mt.binPlusMul(l);
            LL ans=cal(26,l);
            for(int i=0;i<pos;i++)ans-=mat.mz[0][i];
            if(ans<0)ans+=((LL)1<<63)+((LL)1<<63);
            printf("%I64u\n",ans);
        }
        return 0;
    }
  • 相关阅读:
    是时候把邮件发送时间机动化处理了
    GDUT 初赛 01串也疯狂之光棍也有伴
    通达OA 尝试一下进行通达OA的培训
    不让政府系统用Windows 8,他们用什么?
    Mybatis自动生成插件对数据库类型为text的处理
    Mybatis自动生成插件对数据库类型为text的处理
    js的同步与异步
    js的同步与异步
    js的同步与异步
    Java中的数组与集合
  • 原文地址:https://www.cnblogs.com/swm8023/p/2626194.html
Copyright © 2020-2023  润新知