Codeforces 700E. Cool Slogans
Description
给定一个串 \(S\),求一个序列 \(a_i\),满足 \(a_i\) 是原串的子串,且 \(a_i\) 在 \(a_{i-1}\) 中至少出现两次,求这个序列的最大的长度
题面
Solution
根据后缀自动机的性质可以做,首先建出 \(parent\) 树,然后满足条件的序列一定是树上的一条链去掉一些节点
然后就是需要满足出现两次的要求了:
因为是祖先关系,所以至少出现了一次,设 \(pos[i]\) 表示节点 \(i\) 所接受的子串都是以原串中 \(pos[i]\) 这个位置结尾的
另外一次我们就找到这个子串在原串中所代表的区间:\([pos[x]-(len[x]-len[fa[x]]),pos[x]]\),如果这个节点在某个儿子节点所代表的区间中出现了两次,那么就符合要求了
我们用线段树维护 \(pos\) 集合就行了,我们从下往上线段树合并就行了
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
int n,ch[N][26],fa[N],cur=1,cnt=1,len[N],b[N],f[N],ans=0;char s[N];
int pos[N],rt[N],ls[N*30],rs[N*30],tt=0,head[N],nxt[N],to[N],num=0;
inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
inline void Modify(int &x,int l,int r,int sa){
if(!x)x=++tt;
if(l==r)return ;
int mid=(l+r)>>1;
if(sa<=mid)Modify(ls[x],l,mid,sa);
else Modify(rs[x],mid+1,r,sa);
}
inline void ins(int c){
int p=cur;cur=++cnt;len[cur]=len[p]+1;
for(;p && !ch[p][c];p=fa[p])ch[p][c]=cur;
if(!p)fa[cur]=1;
else{
int q=ch[p][c];
if(len[p]+1==len[q])fa[cur]=q;
else{
int nt=++cnt;len[nt]=len[p]+1;
memcpy(ch[nt],ch[q],sizeof(ch[nt]));
fa[nt]=fa[q];fa[q]=fa[cur]=nt;
for(;p && ch[p][c]==q;p=fa[p])ch[p][c]=nt;
}
}
}
inline int merge(int x,int y){
if(!x || !y)return x+y;
int c=++tt;
ls[c]=merge(ls[x],ls[y]);
rs[c]=merge(rs[x],rs[y]);
return c;
}
inline void dfs(int x){
for(int i=head[x];i;i=nxt[i]){
dfs(to[i]),rt[x]=merge(rt[x],rt[to[i]]);
if(!pos[x])pos[x]=pos[to[i]];
}
}
inline bool qry(int x,int l,int r,int sa,int se){
if(!x)return false;
if(sa<=l && r<=se)return true;
int mid=(l+r)>>1;
if(se<=mid)return qry(ls[x],l,mid,sa,se);
if(sa>mid)return qry(rs[x],mid+1,r,sa,se);
return qry(ls[x],l,mid,sa,mid)|qry(rs[x],mid+1,r,mid+1,se);
}
inline void dfs1(int x){
for(int i=head[x],t,u;i;i=nxt[i]){
u=to[i];
t=qry(rt[b[x]],1,n,pos[u]-len[u]+len[b[x]],pos[u]-1);
if(t)f[u]=f[x]+1,b[u]=u;
else f[u]=f[x],b[u]=b[x];
dfs1(u);
}
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
scanf("%d%s",&n,s+1);
for(int i=1;i<=n;i++)
ins(s[i]-'a'),pos[cur]=i,Modify(rt[cur],1,n,i);
for(int i=2;i<=cnt;i++)link(fa[i],i);
dfs(1);
for(int i=head[1];i;i=nxt[i])b[to[i]]=to[i],f[to[i]]=1,dfs1(to[i]);
for(int i=2;i<=cnt;i++)ans=max(ans,f[i]);
printf("%d\n",ans);
return 0;
}
Codeforces 700E. Cool Slogans的更多相关文章
- Codeforces 700E. Cool Slogans 字符串,SAM,线段树合并,动态规划
原文链接https://www.cnblogs.com/zhouzhendong/p/CF700E.html 题解 首先建个SAM. 一个结论:对于parent树上任意一个点x,以及它所代表的子树内任 ...
- Codeforces.700E.Cool Slogans(后缀自动机 线段树合并 DP)
题目链接 \(Description\) 给定一个字符串\(s[1]\).一个字符串序列\(s[\ ]\)满足\(s[i]\)至少在\(s[i-1]\)中出现过两次(\(i\geq 2\)).求最大的 ...
- [LOJ 6288]猫咪[CF 700E]Cool Slogans
[LOJ 6288]猫咪[CF 700E]Cool Slogans 题意 给定一个字符串 \(T\), 求一个最大的 \(K\) 使得存在 \(S_1,S_2,\dots,S_k\) 满足 \(S_1 ...
- SA / SAM 题目集
上一次做 SA / SAM 相关的题还要数到某场毒瘤 NOIP 模拟赛--这么久没做了都快忘光了--写点东西记录一些最近做到的水好题. LOJ2059 「TJOI / HEOI2016」字符串 题意 ...
- 【CF700E】Cool Slogans(后缀自动机)
[CF700E]Cool Slogans(后缀自动机) 题面 洛谷 CodeForces 题解 构建后缀自动机,求出后缀树 现在有个比较明显的\(dp\) 设\(f[i]\)表示从上而下到达当前点能够 ...
- Codeforces 1063F - String Journey(后缀数组+线段树+dp)
Codeforces 题面传送门 & 洛谷题面传送门 神仙题,做了我整整 2.5h,写篇题解纪念下逝去的中午 后排膜拜 1 年前就独立切掉此题的 ymx,我在 2021 年的第 5270 个小 ...
- python爬虫学习(5) —— 扒一下codeforces题面
上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...
- 【Codeforces 738D】Sea Battle(贪心)
http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...
- 【Codeforces 738C】Road to Cinema
http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...
随机推荐
- Beta总结
45°炸 031502601 蔡鸿杰 031502604 陈甘霖 031502632 伍晨薇 一.写在Beta项目前 Beta 凡 事 预 则 立 二.GitHub传送门 Beta冲刺重要版本 三.用 ...
- Alpha冲刺Day7
Alpha冲刺Day7 一:站立式会议 今日安排: 由林静和周静平共同完成企业风险分级展示这一模块的分级列表展示,该模块主要提供企业自查风险的条件查询功能 由黄腾飞和张梨贤共同完成企业风险分级展示的分 ...
- 《Effective Objective-C 2.0》摘要
前一段时间将<Effective Objective-C 2.0>这本书浏览了一遍,说一下几个觉得比较有意思的知识点. 感觉这本书是ios开发必看的一本书,最基础的,以及稍微高阶一点的oc ...
- JAVA线程概念
一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在 ...
- 开始 Python 之旅
开始 Python 之旅 课程来源 本课程基于 Python for you and me 教程翻译制作,其中参考了 Python tutorial 和 The Python Standard Lib ...
- 【iOS】Swift GCD-下
欢迎来到本GCD教程的第二同时也是最终部分! 在第一部分中,你学到了并发,线程以及GCD的工作原理.通过使用dispatch_barrrier和dispatch_sync,你做到了让PhotoMana ...
- 【基础知识】Flex-弹性布局原来如此简单!!
简言 布局的传统解决方案是基于盒状模型,依赖 display + position + float 方式来实现,灵活性较差.2009年,W3C提出了一种新的方案-Flex,Flex是Flexible ...
- UTF-8 UTF-16 UTF-32 最根本的区别?
昨天看书的时候突然发现UTF-16 我好像还没见过这个东西 也可能忘记了 反正现在对自己科普一下吧 最根本的区别 UTF-32 把所有的字符都用32bit -- 4个字节 来表示 UTF-16 和 ...
- H5 FormData对象的作用及用法
JS: function uploadFileAndParam() { var url = "http://localhost:42561/api/upload/UploadPost&quo ...
- 20165230 2017-2018-2 《Java程序设计》第4周学习总结
20165230 2017-2018-2 <Java程序设计>第4周学习总结 教材学习内容总结 子类与继承 通过class 子类名 extends 父类名定义子类.子类只能继承一个父类,关 ...