【题解】CF700E
Cool Slogans
给定一个字符串 ,要求构造字符串序列 ,满足任意 都是 的子串,且任意 ,都有 在 中出现了至少 次(可以有重叠部分,只要起始、结尾位置不同即可)。
求可能的最大的 的值(即序列的最大可能长度)。
。
题解
经典可持久化线段树合并endpos,父节点能转移到子节点即是在子节点对应的区间内能存在两个父节点的endpos,随便瞎搞一下就行。
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
int f=1,j=0;
char w=getchar();
while(!isdigit(w)){
if(w=='-')f=-1;
w=getchar();
}
while(isdigit(w)){
j=j*10+w-'0';
w=getchar();
}
return f*j;
}
const int N=200010,M=400010;
int n,cnt=1;
char s[N];
int head[M],fro[M],to[M],tail;
inline void adlin(int x,int y){
to[++tail]=y,fro[tail]=head[x],head[x]=tail;
return ;
}
int pos[M];
struct SAM{
int len[M],to[M][26],lin[M],last=1;
inline void insert(int x,int pla){
int p=last,cur=++cnt;
len[cur]=len[p]+1,last=cur,pos[cur]=pla;
while(p&&!to[p][x])to[p][x]=cur,p=lin[p];
if(!p)return lin[cur]=1,void(0);
int q=to[p][x];
if(len[q]==len[p]+1)return lin[cur]=q,void(0);
int clone=++cnt;
len[clone]=len[p]+1,memcpy(to[clone],to[q],sizeof(to[clone])),lin[clone]=lin[q],pos[clone]=pos[q];
lin[q]=lin[cur]=clone;
while(p&&to[p][x]==q)to[p][x]=clone,p=lin[p];
return ;
}
}sam;
int rt[M];
struct SegTree{
int ls[M*80],rs[M*80],tot;
void add(int &u,int v,int l,int r,int aim){
u=++tot;
if(l==r)return ;
int mid=(l+r)/2;
if(aim<=mid)rs[u]=rs[v],add(ls[u],ls[v],l,mid,aim);
else ls[u]=ls[v],add(rs[u],rs[v],mid+1,r,aim);
return ;
}
bool get(int u,int l,int r,int L,int R){
if(!u)return false;
if(L<=l&&r<=R)return true;
bool ansn=false;
int mid=(l+r)/2;
if(L<=mid)ansn|=get(ls[u],l,mid,L,R);
if(R>mid)ansn|=get(rs[u],mid+1,r,L,R);
return ansn;
}
void merge(int &u,int a,int b,int l,int r){
if(!a||!b)return u=a|b,void(0);
u=++tot;
int mid=(l+r)/2;
merge(ls[u],ls[a],ls[b],l,mid);
merge(rs[u],rs[a],rs[b],mid+1,r);
return ;
}
}tree;
int f[M],g[M];
void dfs1(int u){
// cout<<"wk:"<<u<<":"<<g[u]<<"-"<<tree.tr[rt[u]]<<"\n";
// if(sam.len[u]==1)g[u]=1;
for(int k=head[u];k;k=fro[k]){
int x=to[k];
dfs1(x);
tree.merge(rt[u],rt[u],rt[x],1,n);
}
return ;
}
int ans;
void dfs2(int u){
// cout<<"wk:"<<u<<":"<<f[u]<<" "<<g[u]<<"-"<<tree.tr[rt[u]]<<":"<<sam.len[u]<<"\n";
ans=max(f[u],ans);
for(int k=head[u];k;k=fro[k]){
int x=to[k];
if(tree.get(rt[g[u]],1,n,pos[x]-sam.len[x]+sam.len[g[u]],pos[x]-1)){
f[x]=f[u]+1,g[x]=x;
}
else{
f[x]=f[u],g[x]=g[u];
}
if(sam.len[x]==1)f[x]=1,g[x]=x;
// cout<<u<<"->"<<x<<":"<<pos[x]<<" "<<f[x]<<"-"<<pos[g[x]]<<"-"<<sam.len[x]<<" "<<sam.len[g[u]]<<"\n";
dfs2(x);
}
return ;
}
signed main(){
n=rd(),scanf("%s",s+1);
for(int i=1;i<=n;i++)sam.insert(s[i]-'a',i);
// for(int i=1;i<=cnt;i++)cout<<sam.lin[i]<<"->"<<i<<":"<<pos[i]<<"\n";
for(int i=cnt;i>=2;i--)adlin(sam.lin[i],i),g[i]=1;
for(int i=2;i<=cnt;i++)tree.add(rt[i],rt[i],1,n,pos[i]);
dfs1(1),dfs2(1);
printf("%d\n",ans);
return 0;
}
/*
7
daddddd
21
abcaaaaabbcbacbabcbcb
*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】