CTSC2012 熟悉的文章

Description

link

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

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

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

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

Solution

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

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

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

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

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

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

如果最后 \(f_l\ge p\times0.9\) 就表示当下的 \(p\) 满足

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

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

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

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

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

Code

#include
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=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\n",ans);
		}
		return 0;
	}
}
signed main(){return yspm::main();} 

你可能感兴趣的:(CTSC2012 熟悉的文章)