• CF1037H Security 线段树合并 SAM


    LINK:Security

    求一个严格大于T的字符串 是原字符串S[L,R]的子串。

    容易想到尽可能和T相同 然后再补一个尽可能小的字符即可。

    出于这种思想 可以在SAM上先跑匹配 然后枚举加哪个字符 判定即可。

    判定s是否在[L,R]中出现过 最快的方法 就是right集了。

    这个可以线段树合并完成 注意 合并的时候 需要新建节点 防止把儿子的信息给改了。

    倒着贪心即可。空间复杂度大概是nlog^2左右的注意开够。(我也不太会计算空间

    const int MAXN=100010;
    int n,m,id,len;
    int last=1,cnt=1,top;
    char a[MAXN<<1],b[MAXN<<1];
    struct wy
    {
    	int fa,len;
    	int ch[26];
    }t[MAXN<<1];
    int root[MAXN<<1],q[MAXN<<1],c[MAXN<<1],pre[MAXN<<1];
    struct jl{int l,r,sum;}s[MAXN*200];
    inline void insert(int x)
    {
    	int p=last;
    	int np=last=++cnt;
    	len(np)=len(p)+1;
    	while(p&&!t[p].ch[x])
    	{
    		t[p].ch[x]=np;
    		p=f(p);
    	}
    	if(!p)f(np)=1;
    	else
    	{
    		int q=t[p].ch[x];
    		if(len(p)+1==len(q))f(np)=q;
    		else
    		{
    			int nq=++cnt;
    			t[nq]=t[q];
    			len(nq)=len(p)+1;
    			f(np)=f(q)=nq;
    			while(p&&t[p].ch[x]==q)
    			{
    				t[p].ch[x]=nq;
    				p=f(p);
    			}
    		}
    	}
    }
    inline void change(int &p,int l,int r,int x)
    {
    	if(!p)p=++id;
    	if(l==r){++sum(p);return;}
    	int mid=(l+r)>>1;
    	if(x<=mid)change(l(p),l,mid,x);
    	else change(r(p),mid+1,r,x);
    	sum(p)=sum(l(p))+sum(r(p));
    }
    inline void topsort()
    {
    	rep(1,cnt,i)++c[len(i)];
    	rep(1,cnt,i)c[i]+=c[i-1];
    	rep(1,cnt,i)q[c[len(i)]--]=i;
    }
    inline int merge(int x,int y,int l,int r)
    {
    	if(!x||!y)return x|y;
    	int w=++id;
    	if(l==r){sum(w)=sum(x)+sum(y);return w;}
    	int mid=(l+r)>>1;
    	l(w)=merge(l(x),l(y),l,mid);
    	r(w)=merge(r(x),r(y),mid+1,r);
    	sum(w)=sum(l(w))+sum(r(w));
    	return w;
    }
    inline int ask(int p,int l,int r,int L,int R)
    {
    	if(!p||L>R)return 0;
    	if(L<=l&&R>=r)return sum(p);
    	int mid=(l+r)>>1,ww=0;
    	if(L<=mid)ww+=ask(l(p),l,mid,L,R);
    	if(R>mid)ww+=ask(r(p),mid+1,r,L,R);
    	return ww;
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	gc(a);len=strlen(a+1);
    	rep(1,len,i)insert(a[i]-'a'),change(root[last],1,len,i);
    	topsort();gt(n);
    	fep(cnt,2,i)root[f(q[i])]=merge(root[f(q[i])],root[q[i]],1,len);
    	rep(1,n,i)
    	{
    		int x,y;
    		gt(x);gt(y);gc(b);
    		int now=1,last=-1,flag=0;top=0;
    		int len1=strlen(b+1);
    		rep(1,len1,j)
    		{
    			int cc=b[j]-'a';
    			if(t[now].ch[cc])pre[t[now].ch[cc]]=now,now=t[now].ch[cc],a[++top]=b[j];
    			else {last=b[j]-'a';break;}
    		}
    		while(now)
    		{
    			rep(last+1,25,j)
    			{
    				if(flag)break;
    				int ww=t[now].ch[j];
    				if(ww)
    				{
    					if(ask(root[ww],1,len,x+top,y))
    					{
    						a[++top]=j+'a';
    						flag=1;
    					}
    				}
    			}
    			if(flag)break;
    			now=pre[now];last=b[top]-'a';
    			--top;
    		}
    		if(!flag){puts("-1");}
    		else {rep(1,top,i)printf("%c",a[i]);puts("");}
    	}
    	return 0;
    }
    
  • 相关阅读:
    vue 设置请求超时时间处理
    element 表格只展开一行(点击下一行上一行关闭)
    element菜单刷新后定位问题?
    自己觉得不错的滚动条样式
    $.ajax()方法详解
    安卓获取自有证书的SHA1码
    sortable.js 拖拽排序及配置项说明
    uni-app 引入本地iconfont的正确姿势以及阿里图标引入
    mui slider禁止滑动
    stl源码剖析 详细学习笔记 仿函数
  • 原文地址:https://www.cnblogs.com/chdy/p/12831883.html
Copyright © 2020-2023  润新知