zoukankan      html  css  js  c++  java
  • CTSC2012 熟悉的文章

    Description

    link

    给定一些模板串和一些询问,每个询问以字符串的形式给出

    对于每个询问给出的字符串,可以将其进行分割,使得其子串是某个模板串的子串

    同时有一个标量 (p) 为分割方案中最小的 子串 的长度

    求所有方案中的 (p_{max})

    Solution

    求子串的方法就是后缀自动机,然后这题先对所有模板串建广义 (sam)

    这个 (p) 是可以二分的,然后把问题转成判定性问题

    (f_i) 为当前询问前 (i) 个字符能匹配的最大长度,然后有

    [f_i=max( maxlimits_{j=i-match_i}^{i-p}f_j+i-j,f_{i-1}) ]

    其中 (match_i) 是当前字符在广义 (sam) 的最长匹配长度

    可以把询问放到上面跑一下求出来

    如果最后 (f_lge p imes0.9) 就表示当下的 (p) 满足

    然后我们发现这个方程并不能满足我们的时间需求

    看看式子,有种斜率优化的冲动

    打个表发现两边都满足不降……

    (这里证明?看看nofind的博客吧)

    然后直接单调队列优化这个过程即可

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int N=1.1e6+10; 
    	int fa[N<<1],ch[N<<1][2],len[N<<1],tot=1,las=1,n,m;
    	inline void copy(int x,int y)
    	{
    		for(int i=0;i<2;++i) ch[x][i]=ch[y][i];
    		return ;
    	}
    	inline void extend(int x)
    	{
    		int tmp=las,np=las=++tot; len[np]=len[tmp]+1;
    		while(tmp&&!ch[tmp][x]) ch[tmp][x]=np,tmp=fa[tmp];
    		if(!tmp) return fa[np]=1,void();
    		int q=ch[tmp][x]; 
    		if(len[q]==len[tmp]+1) return fa[np]=q,void();
    		int clone=++tot; fa[clone]=fa[q]; fa[q]=fa[np]=clone; copy(clone,q);
    		len[clone]=len[tmp]+1;
    		while(tmp&&ch[tmp][x]==q) ch[tmp][x]=clone,tmp=fa[tmp]; 
    		return ;
    	}
    	char s[N];
    	int maxx[N],q[N],h,t,l,f[N],T;
    	inline void prework()
    	{
    		int res=0,now=1; l=strlen(s+1);
    		for(int i=1;i<=l;++i)
    		{
    			int t=s[i]-'0';
    			while(now&&!ch[now][t]) now=fa[now],res=len[now];
    			if(now) now=ch[now][t],res++;
    			else now=1,res=0; 
    			maxx[i]=res;
    		} return ;
    	}
    	inline bool check(int x)
    	{
    		h=1; t=0; q[1]=0; 
    		for(int i=1;i<x;++i) f[i]=0;
    		for(int i=x;i<=l;++i) 
    		{
    			f[i]=f[i-1];
    			while(h<=t&&f[q[t]]-q[t]<f[i-x]-i+x) --t;
    			q[++t]=i-x; 
    			while(h<=t&&q[h]<i-maxx[i]) ++h;
    			if(h<=t) f[i]=max(f[i],f[q[h]]+i-q[h]);
    		}
    		
    		return f[l]*10>=l*9;
    	}
    	signed main()
    	{
    		T=read(); m=read();
    		for(int i=1,tl;i<=m;++i) 
    		{
    			scanf("%s",s+1); tl=strlen(s+1); las=1; 
    			for(int j=1;j<=tl;++j) extend(s[j]-'0');
    			
    		} 
    		while(T--)
    		{
    			scanf("%s",s+1); prework();
    			
    			int l=1,r=strlen(s+1),ans=0;
    			while(l<=r)
    			{
    				int mid=(l+r)>>1;
    				if(check(mid)) ans=mid,l=mid+1;
    				else r=mid-1;
    			}printf("%lld
    ",ans);
    		}
    		return 0;
    	}
    }
    signed main(){return yspm::main();} 
    
  • 相关阅读:
    一秒解决element容器布局显示内部调节框的问题
    操作管理员
    Linux_网络基础管理
    如何解决在WordPress安装Redis插件时需要输入FTP问题?
    如何在我的EC2实例状态更改时获取自定义电子邮件通知
    利用S3fs在Amazon EC2 Linux实例上挂载S3存储桶
    源码安装Apache(httpd)
    Linux_源码安装包管理理论概述
    Linux_yum命令详解
    Linux_yum仓库管理
  • 原文地址:https://www.cnblogs.com/yspm/p/13289710.html
Copyright © 2011-2022 走看看