luoguCF1037H Security
Posted nofind
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguCF1037H Security相关的知识,希望对你有一定的参考价值。
题意
显然是贪心。
先建出SAM,之后能走相同的字符就走相同的字符,实在不行再走一个比它大的。
考虑怎么处理([l,r])的限制,我们只要用线段树合并维护出每个点的endpos集合,到时候判断下走这一步是否合法即可。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int T,n,tot,cnt;
int root[maxn],head[maxn];
char s[maxn],t[maxn],ans[maxn];
inline int read()
{
char c=getchar();int res=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
return res*f;
}
struct edge{int to,nxt;}e[maxn<<1];
inline void add(int u,int v){e[++cnt].nxt=head[u];head[u]=cnt;e[cnt].to=v;}
struct Seg
{
#define lc(p) (seg[p].lc)
#define rc(p) (seg[p].rc)
#define sum(p) (seg[p].sum)
int lc,rc,sum;
}seg[maxn*50];
void insert(int &p,int l,int r,int pos)
{
if(!p)p=++tot;
sum(p)++;
if(l==r)return;
int mid=(l+r)>>1;
if(pos<=mid)insert(lc(p),l,mid,pos);
else insert(rc(p),mid+1,r,pos);
}
int query(int p,int l,int r,int ql,int qr)
{
if(!p)return 0;
if(l>=ql&&r<=qr)return sum(p);
int mid=(l+r)>>1,res=0;
if(ql<=mid)res+=query(lc(p),l,mid,ql,qr);
if(qr>mid)res+=query(rc(p),mid+1,r,ql,qr);
//cerr<<"res::"<<res<<endl;
return res;
}
int merge(int p,int q,int l,int r)
{
if(!p||!q)return p+q;
int x=++tot,mid=(l+r)>>1;
sum(x)=sum(p)+sum(q);
if(l==r)return x;
lc(x)=merge(lc(p),lc(q),l,mid);
rc(x)=merge(rc(p),rc(q),mid+1,r);
return x;
}
struct SAM
{
int tot,last;
int fa[maxn],len[maxn];
int ch[maxn][30];
SAM(){last=tot=1;}
inline void add(int c)
{
int now=++tot;len[now]=len[last]+1;
int p=last;last=now;
while(p&&!ch[p][c])ch[p][c]=now,p=fa[p];
if(!p){fa[now]=1;return;}
int q=ch[p][c];
if(len[q]==len[p]+1)fa[now]=q;
else
{
int nowq=++tot;
len[nowq]=len[p]+1;
memcpy(ch[nowq],ch[q],sizeof(ch[q]));
fa[nowq]=fa[q];fa[q]=fa[now]=nowq;
while(p&&ch[p][c]==q)ch[p][c]=nowq,p=fa[p];
}
}
}sam;
void dfs(int x)
{
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
dfs(y);root[x]=merge(root[x],root[y],1,n);
}
}
inline void solve(int l,int r,char* s)
{
int now=1,tot=1,len=strlen(s+1);
while(2333)
{
ans[tot]='#';
for(int i=max(s[tot]-'a'+1,0);i<26;i++)
if(sam.ch[now][i]&&query(root[sam.ch[now][i]],1,n,l+tot-1,r)>0)
{
ans[tot]=i+'a';
break;
}
if(tot==len+1||!sam.ch[now][s[tot]-'a']||!query(root[sam.ch[now][s[tot]-'a']],1,n,l+tot-1,r))break;
now=sam.ch[now][s[tot]-'a'];
tot++;
}
while(tot&&ans[tot]=='#')tot--;
if(!tot)puts("-1");
else
{
for(int i=1;i<tot;i++)putchar(s[i]);
putchar(ans[tot]);puts("");
}
}
int main()
{
scanf("%s",s+1);n=strlen(s+1);
for(int i=1;i<=n;i++)sam.add(s[i]-'a'),insert(root[sam.last],1,n,i);
for(int i=2;i<=sam.tot;i++)add(sam.fa[i],i);
dfs(1);
T=read();
while(T--)
{
int l=read(),r=read();
scanf("%s",t+1);
solve(l,r,t);
}
return 0;
}
以上是关于luoguCF1037H Security的主要内容,如果未能解决你的问题,请参考以下文章
CF1037H Security 后缀自动机 + right集合线段树合并 + 贪心
Spring Security:无法让真正的用户使用显示过期的 SessionRegistry 登录