zoukankan      html  css  js  c++  java
  • 【BZOJ4861】【BJOI2017】—魔法咒语(AC自动机+矩阵快速幂优化dp)

    传送门

    l100lle 100
    显然的自动机上dpdp就完了

    l1e8lle1e8时直接dpdp显然是不行的
    但是发现基本串长度不大于二
    考虑矩乘优化
    a[i][j]a[i][j]表示有几个基本串使得在自动机上ii走到jj
    如果所有串长相同就可以直接快速幂了
    但是串长有1122
    不同长度不好处理拼起来的情况
    A1A_1表示长度为1的串的转移矩阵
    A2A_2为长度为2的
    考虑构造矩阵

    [0A2IA1]egin{bmatrix} 0&A_2\ I &A_1 end{bmatrix}

    这样的转移矩阵就可以了

    #include<bits/stdc++.h>
    using namespace std;
    #define gc getchar
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    int n,m,l;
    const int N=55,M=105;
    const int mod=1e9+7;
    inline int add(int a,int b){return (a+=b)>=mod?a-=mod:a;}
    inline void Add(int &a,int b){(a+=b)>=mod?a-=mod:0;}
    inline int dec(int a,int b){return (a-=b)<0?a+=mod:a;}
    inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
    inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
    inline void Mul(int &a,int b){a=mul(a,b);}
    inline int ksm(int a,int b,int res=1){
        for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));return res;
    }
    inline void chemx(int &a,int b){a<b?a=b:0;}
    inline void chemn(int &a,int b){a>b?a=b:0;}
    namespace Ac{
    	int nxt[M][26],tot,fail[M],ed[M];
    	inline void insert(char *s){
    		int p=0;
    		for(int i=1,len=strlen(s+1);i<=len;i++){
    			int c=s[i]-'a';
    			if(!nxt[p][c])nxt[p][c]=++tot;
    			p=nxt[p][c];
    		}
    		ed[p]++;
    	}
    	queue<int> q;
    	inline void build(){
    		for(int i=0;i<26;i++){
    			if(nxt[0][i])fail[nxt[0][i]]=0,q.push(nxt[0][i]);
    		}
    		
    		while(!q.empty()){
    			int p=q.front();q.pop();
    			for(int c=0;c<26;c++){
    				int v=nxt[p][c];
    				if(!v)nxt[p][c]=nxt[fail[p]][c];
    				else fail[v]=nxt[fail[p]][c],q.push(v);
    			}
    			ed[p]+=ed[fail[p]];
    		}
    	}
    	inline int go(int p,char *s){
    		if(ed[p])return -1;
    		for(int i=1,len=strlen(s+1);i<=len;i++){
    			int c=s[i]-'a';
    			p=nxt[p][c];
    			if(ed[p])return -1;
    		}
    		return p;
    	}
    }
    using namespace Ac;
    char s[N][M],t[N][M];
    int len[N];
    namespace solve1{
    	int f[M][M];
    	inline void main(){
    		f[0][0]=1;
    		for(int i=0;i<l;i++)
    		for(int j=0;j<=tot;j++)
    			for(int k=1;k<=n;k++)
    			if(i+len[k]<=l){
    				int p=go(j,s[k]);
    				if(p!=-1)
    					Add(f[i+len[k]][p],f[i][j]);
    			}
    		int res=0;
    		for(int i=0;i<=tot;i++)Add(res,f[l][i]);
    		cout<<res<<'
    ';
    	}
    }
    namespace solve2{
    	int lim;
    	struct mat{
    		int a[M*2][M*2];
    		mat(){memset(a,0,sizeof(a));}
    		friend inline mat operator *(const mat &a,const mat &b){
    			mat c=mat();
    			for(int i=0;i<=lim;i++)
    			for(int k=0;k<=lim;k++)
    			for(int j=0;j<=lim;j++)
    			Add(c.a[i][j],mul(a.a[i][k],b.a[k][j]));
    			return c;
    		}
    	}ret,ans;
    	inline mat ksm(mat a,int b,mat res){
    		for(;b;b>>=1,a=a*a)if(b&1)res=res*a;
    		return res;
    	}
    	inline void main(){
    		lim=tot*2+1;
    		for(int i=0;i<=tot;i++)ret.a[i+tot+1][i]=1;
    		for(int i=0;i<=tot;i++)
    		for(int j=1;j<=n;j++){
    			if(len[j]==2){
    				int p=go(i,s[j]);
    				if(p!=-1)ret.a[i][p+tot+1]++;
    			}
    		}
    		for(int i=0;i<=tot;i++)
    		for(int j=1;j<=n;j++){
    			if(len[j]==1){
    				int p=go(i,s[j]);
    				if(p!=-1)ret.a[i+tot+1][p+tot+1]++;
    			}
    		}
    		ret=ksm(ret,l-1,ret);
    		ans.a[0][tot+1]=1;
    		ans=ans*ret;
    		int res=0;
    		for(int i=0;i<=tot;i++)
    		Add(res,ans.a[0][i+tot+1]);
    		cout<<res;
    	}
    }
    int main(){
    	n=read(),m=read(),l=read();
    	for(int i=1;i<=n;i++)scanf("%s",s[i]+1),len[i]=strlen(s[i]+1);;
    	for(int i=1;i<=m;i++)scanf("%s",t[i]+1),insert(t[i]);
    	build();
    	if(l<=100)solve1::main();
    	else solve2::main();
    }
    
  • 相关阅读:
    [Python Study Notes]with的使用
    [Python Study Notes]pynput实现对键盘控制与监控
    [Python Study Notes]pynput实现对鼠标控制
    [Python Study Notes]WdSaveFormat 枚举
    voip通话分析(含语音质量)
    纯Python给ulaw wav文件加头
    BAE+Python+Django+Wechatpy+Baidu weather api +微信订阅号 = 实现微信查询天气
    Python爬虫抓取某音乐网站MP3(下载歌曲、存入Sqlite)
    Python调用C++DLL函数出错String类型问题
    聊聊Python ctypes 模块(转载)
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328777.html
Copyright © 2011-2022 走看看