CF700E Cool Slogans 题解
考虑转化题意,容易发现我们一定可以找到一个\(k\)最大的\(s\)序列使得\(s_{i-1}\)为\(s_i\)的\(boder\)。然后建立后缀自动机,每一个父节点是它的后缀,然后维护一条链,考虑能多出一个\(s_i\)就多出一个\(s_i\)(省流:贪心),然后每个点维护\(k\)最大时节点的最小的位置,考虑我们要判断一个区间是否出现,我们发现可以直接用\(endpos\)集合,假设\(i\)为\(j\)的祖先,\(pos_j\)为\(j\)的\(endpos\)集合中的一个值,那么\(i\)的\(endpos\)集合中一定含有\(pos_j\),只需要判断\([pos_j-len_j+len_{i},pos_j-1]\)中有没有出现的\(endpos\)值就可以了,容易发现对于一个节点,\(i\)一定是它祖先中最后一个被更新答案的节点。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=8e5+10;
struct edge{
map<int,int>ch;
int link;
int pos;
int len;
int rt;
}tree[maxn];
struct node{
int ls;
int rs;
}t[maxn<<5];
int lst,n,f[maxn],tot=1,idd,ans,top[maxn],lin,pos[maxn],nn;
vector<int>tu[maxn];
string s;
void insert(int c){
int p=lst,np,q,nq;
tot++;
np=tot;
pos[np]=nn;
tree[np].len=tree[p].len+1;
for(;p&&!tree[p].ch[c];p=tree[p].link){
tree[p].ch[c]=np;
}
if(!p){
tree[np].link=1;
}
else{
q=tree[p].ch[c];
if(tree[p].len+1==tree[q].len){
tree[np].link=q;
}
else{
tot++;
nq=tot;
tree[nq]=tree[q];
pos[nq]=pos[q];
tree[nq].len=tree[p].len+1;
tree[q].link=nq;
tree[np].link=nq;
for(;p&&tree[p].ch[c]==q;p=tree[p].link){
tree[p].ch[c]=nq;
}
}
}
lst=np;
return;
}
void add(int &id,int l,int r,int q){
if(!id){
idd++;
id=idd;
}
if(l==r){
return;
}
int mid=(l+r)/2;
if(q<=mid){
add(t[id].ls,l,mid,q);
}
else{
add(t[id].rs,mid+1,r,q);
}
return;
}
int merge(int q,int w){
if(!q||!w){
return q+w;
}
idd++;
int zhi=idd;
t[zhi].ls=merge(t[q].ls,t[w].ls);
t[zhi].rs=merge(t[q].rs,t[w].rs);
return zhi;
}
bool query(int id,int l,int r,int q,int w){
if(!id){
return 0;
}
if(q<=l&&r<=w){
return 1;
}
int mid=(l+r)/2;
if(q<=mid&&query(t[id].ls,l,mid,q,w)){
return 1;
}
if(w>mid&&query(t[id].rs,mid+1,r,q,w)){
return 1;
}
return 0;
}
void dfs1(int q){
for(int i=0;i<(int)tu[q].size();i++){
dfs1(tu[q][i]);
tree[q].rt=merge(tree[q].rt,tree[tu[q][i]].rt);
}
return;
}
void dfs(int q){
if(tree[q].link==1){
f[q]=1;
top[q]=q;
}
else{
int p=pos[q];
lin=query(tree[top[tree[q].link]].rt,1,n,p-tree[q].len+tree[top[tree[q].link]].len,p-1);
if(lin){
f[q]=f[tree[q].link]+1;
top[q]=q;
}
else{
f[q]=f[tree[q].link];
top[q]=top[tree[q].link];
}
}
for(int i=0;i<(int)tu[q].size();i++){
dfs(tu[q][i]);
}
ans=max(ans,f[q]);
return;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>s;
lst=1;
for(int i=0;i<(int)s.size();i++){
nn=i+1;
insert(s[i]-'a');
add(tree[lst].rt,1,n,nn);
}
for(int i=2;i<=tot;i++){
tu[tree[i].link].push_back(i);
}
dfs1(1);
for(int i=0;i<(int)tu[1].size();i++){
dfs(tu[1][i]);
}
cout<<ans;
return 0;
}
浙公网安备 33010602011771号