• HDU-2243 考研路茫茫——单词情结(AC自动机)


    题目大意:给n个单词,长度不超过L的单词有多少个包含n个单词中的至少一个单词。

    题目分析:用长度不超过L的单词书目减去长度在L之内所有不包含任何一个单词的书目。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<queue>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    # define LL long long
    # define ULL unsigned long long
    
    struct Matrix
    {
        int n;
        ULL ele[35][35];
        Matrix(int _n):n(_n){
            for(int i=0;i<n;++i) for(int j=0;j<n;++j)
                ele[i][j]=0;
        }
    };
    int ch[35][26];
    int fail[35],cnt;
    bool word[35];
    
    void init()
    {
        cnt=0;
        memset(ch,-1,sizeof(ch));
        memset(word,false,sizeof(word));
    }
    
    int idx(char c)
    {
        return c-'a';
    }
    
    void insert(char *s)
    {
        int n=strlen(s);
        int r=0;
        for(int i=0;i<n;++i){
            int c=idx(s[i]);
            if(ch[r][c]==-1) ch[r][c]=++cnt;
            r=ch[r][c];
        }
        word[r]=true;
    }
    
    void getFail()
    {
        queue<int>q;
        fail[0]=0;
        for(int i=0;i<26;++i){
    		if(ch[0][i]==-1){
    			ch[0][i]=0;
    		}else{
    			fail[ch[0][i]]=0;
    			q.push(ch[0][i]);
    		}
        }
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            if(word[fail[u]]) word[u]=true;
            for(int i=0;i<26;++i){
                if(ch[u][i]==-1)
                    ch[u][i]=ch[fail[u]][i];
                else{
                    fail[ch[u][i]]=ch[fail[u]][i];
                    q.push(ch[u][i]);
                }
            }
        }
    }
    
    Matrix getMatrix()
    {
    	Matrix mat(cnt+1);
    	for(int i=0;i<mat.n;++i)
    		for(int j=0;j<26;++j) if(!word[ch[i][j]])
    			++mat.ele[i][ch[i][j]];
        ++mat.n;
        for(int i=0;i<mat.n;++i){
    		mat.ele[mat.n-1][i]=0;
    		mat.ele[i][mat.n-1]=1;
        }
        return mat;
    }
    
    Matrix mul(Matrix a,Matrix b)
    {
        Matrix c(a.n);
        for(int i=0;i<c.n;++i) for(int j=0;j<c.n;++j)
    		for(int k=0;k<c.n;++k) c.ele[i][j]+=a.ele[i][k]*b.ele[k][j];
        return c;
    }
    
    Matrix myPow(Matrix a,LL k)
    {
        Matrix mat(a.n);
    	for(int i=0;i<mat.n;++i) mat.ele[i][i]=1;
    	while(k>0){
    		if(k&1) mat=mul(mat,a);
    		a=mul(a,a);
    		k>>=1;
    	}
        return mat;
    }
    
    ULL getSum(LL x)
    {
    	Matrix mat(2);
    	mat.ele[0][0]=26;
    	mat.ele[0][1]=1;
    	mat.ele[1][0]=0;
    	mat.ele[1][1]=1;
    	mat=myPow(mat,x);
    	return mat.ele[0][1];
    }
    
    char prefix[8];
    
    int main()
    {
        int n;
        LL L;	
        while(~scanf("%d%lld",&n,&L))
        {
    		init();
            for(int i=0;i<n;++i){
                scanf("%s",prefix);
                insert(prefix);
            }
            getFail();
            Matrix mat=getMatrix();
            mat=myPow(mat,L+1);
            ULL ans1=mat.ele[0][mat.n-1];
            ULL ans2=getSum(L+1);
            cout<<ans2-ans1<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    daper
    存储过程事务
    dengluzhucehaiyouxianshiMVC
    遍历加监听
    类的操作
    轮播图
    定时器的应用(三)
    定时器的应用(二)
    定时器的应用(一)
    延时调用
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5984948.html
Copyright © 2020-2023  润新知