[LOJ 6288]猫咪[CF 700E]Cool Slogans
[LOJ 6288]猫咪[CF 700E]Cool Slogans
题意
给定一个字符串 \(T\), 求一个最大的 \(K\) 使得存在 \(S_1,S_2,\dots,S_k\) 满足 \(S_1\) 是 \(T\) 的子串且 \(\forall 1\le i< k\) 有 \(S_{i+1}\) 是 \(S\) 的双子串.
其中双子串的定义是: 若 \(a\) 在 \(b\) 的至少两个不同位置作为子串出现则 \(a\) 为 \(b\) 的双子串. 出现位置可以重叠.
\(|T|\le 2\times 10^5\).
题解
考试的时候被沙雕题目描述搞得迷迷糊糊的结果没发现是原题←菜的真实
显然对于每个子串我们可以这个子串里挑一个答案最大且的双子串作为这个子串的答案.
我们发现当我们挑出一个子串 \(S_1\) 后, 可以通过对左右端点进行适当缩减来刚好卡到"每一个双子串都是上一个串的一个border"的程度. 因为如果出现了不是border的情况, 可以把前面所有的 \(S_i\) 全都缩短, 不难发现这样并不会导致答案变劣.
那么实际上要计算的就是每个子串最多迭代几个border. 考虑在SAM上DP. SAM的结点上只能控制右端点, 左端点是一个区间, 不难发现只要搞右端点相同就可以了. 线段树合并搞出每个点的 right 集合, 判断一下答案最大的祖先是否能对当前点做出贡献就可以了. 能做出贡献就 \(+1\), 否则就不加.
至于判断, 因为当前 right 集合对应的长度最大为 len 的子串都是完全一样的, 所以随便取一个位置判断就可以了.
参考代码
#include <bits/stdc++.h>
const int MAXN=4e5+10;
struct Node{
int l;
int r;
int cnt;
Node* lch;
Node* rch;
Node(int,int);
void Insert(int);
int Query(int,int);
};
Node* N[MAXN];
int n;
int cnt=1;
int root=1;
int last=1;
int s[MAXN];
int prt[MAXN];
int len[MAXN];
int val[MAXN];
int pos[MAXN];
int tprt[MAXN];
char str[MAXN];
std::map<char,int> chd[MAXN];
int Extend(char);
Node* Merge(Node*,Node*);
int main(){
scanf("%s",str+1);
n=strlen(str+1);
for(int i=1;i<=n;i++){
int x=Extend(str[i]);
N[x]->Insert(pos[x]=i);
}
for(int i=1;i<=cnt;i++)
s[i]=i;
std::stable_sort(s+1,s+cnt+1,[](int a,int b){return len[a]>len[b];});
for(int i=1;i<cnt;i++){
N[prt[s[i]]]=Merge(N[prt[s[i]]],N[s[i]]);
pos[prt[s[i]]]=pos[s[i]];
}
int ans=0;
for(int i=cnt-1;i>=1;i--){
int p=s[i];
if(prt[p]==root){
val[p]=1;
tprt[p]=p;
}
else{
assert(N[p]->Query(pos[p],pos[p]));
int last=tprt[prt[p]];
int cnt=N[last]->Query(pos[p]-len[p]+(len[prt[last]]+1),pos[p]);
if(cnt>=2){
val[p]=val[last]+1;
tprt[p]=p;
}
else{
val[p]=val[last];
tprt[p]=last;
}
}
ans=std::max(ans,val[p]);
}
printf("%d\n",ans);
return 0;
}
void Node::Insert(int x){
++this->cnt;
if(this->l!=this->r){
int mid=(this->l+this->r)>>1;
if(x<=mid){
if(this->lch==NULL)
this->lch=new Node(this->l,mid);
this->lch->Insert(x);
}
else{
if(this->rch==NULL)
this->rch=new Node(mid+1,this->r);
this->rch->Insert(x);
}
}
}
int Extend(char x){
int p=last;
int np=++cnt;
N[last=np]=new Node(1,n);
len[np]=len[p]+1;
while(p&&!chd[p].count(x))
chd[p][x]=np,p=prt[p];
if(!p)
prt[np]=root;
else{
int q=chd[p][x];
if(len[q]==len[p]+1)
prt[np]=q;
else{
int nq=++cnt;
N[nq]=new Node(1,n);
len[nq]=len[p]+1;
chd[nq]=chd[q];
prt[nq]=prt[q];
prt[q]=nq;
prt[np]=nq;
while(p&&chd[p][x]==q)
chd[p][x]=nq,p=prt[p];
}
}
return np;
}
Node* Merge(Node* a,Node* b){
if(a==NULL)
return b;
if(b==NULL)
return a;
Node* cur=new Node(a->l,b->r);
cur->cnt=a->cnt+b->cnt;
cur->lch=Merge(a->lch,b->lch);
cur->rch=Merge(a->rch,b->rch);
return cur;
}
int Node::Query(int l,int r){
if(l<=this->l&&this->r<=r)
return this->cnt;
else{
int ans=0;
if(this->lch&&l<=this->lch->r)
ans+=this->lch->Query(l,r);
if(this->rch&&this->rch->l<=r)
ans+=this->rch->Query(l,r);
return ans;
}
}
Node::Node(int l,int r):l(l),r(r),cnt(0),lch(NULL),rch(NULL){}

[LOJ 6288]猫咪[CF 700E]Cool Slogans的更多相关文章
- NABCD模型(猫咪记单词)
项目需求分析与建议-NABCD模型(猫咪记单词) N (Need 需求) 对于现在的学生,尤其是大学生来说,学习英语是一件非常重要的事.我们有四级六级托福雅思等各种各样的英语方面的考试.而学习英语 ...
- [TYVJ] P1423 GF和猫咪的玩具
GF和猫咪的玩具 描述 Description GF同学和猫咪得到了一个特别的玩具,这个玩具由n个金属环(编号为1---n),和m条绳索组成,每条绳索连接两个不同的金属环,并且长度相同.GF左手拿起金 ...
- 猫咪记单词Beta版使用说明
猫咪记单词Beta版使用说明 一.项目背景 英语四级考试.六级考试.托福.雅思等英语方面的考试是现在大学生必须面对的问题.同时因为学生对手机的使用越来越频繁,而且仅仅通过书本背诵单词又比较无聊坚持的时 ...
- Cal Cat for Mac(猫咪控日历工具)安装
1.软件简介 Cal Cat 是 macOS 系统上一款猫咪控日历工具,可以将系统内置的日历工具美化成猫咪风格的日历,超级可爱的猫咪可是猫咪控的最爱了,喜欢的朋友快快用上吧. 加州猫是一个桌面集 ...
- 猫咪记单词——NABCD模型分析
N ——Need 需求:学习英语是一件非常重要的事.面对各种各样的考试,学习英语,最重要的就是词汇量,背单词是提高词汇量的最直接的方法,但是单纯的背单词太单调.寻找一些合适的,更易于接受的背单词学习英 ...
- 算法 PK 猫咪 | 章鱼保罗后继竟然是只猫?
简评:一只名叫阿喀琉斯(Achilles)的白猫一边小声叫着,一边慵懒地在分别插有俄罗斯和沙特阿拉伯国旗的食盆间踱步.这只看起来并不出众的小猫住在俄罗斯圣彼得堡埃尔米塔日博物馆(State Hermi ...
- TYVJ1423 GF和猫咪的玩具
Description: GF同学和猫咪得到了一个特别的玩具,这个玩具由n个金属环(编号为1---n),和m条绳索组成,每条绳索连接两个不同的金属环,并且长度相同.GF左手拿起金属环L,猫咪右手(或者 ...
- COGS 1191. [Tyvj Feb11] 猫咪的进化
★ 输入文件:neko.in 输出文件:neko.out 简单对比时间限制:1 s 内存限制:128 MB [背景] 对于一只猫咪来说,它是有九条命的.但是并不是所有的猫咪都是这样,只 ...
- CTF 两道web整数溢出题目(猫咪银行和ltshop)
①猫咪银行: (2018中科大hackgame) 一开始给十个CTB,而flag需要20个CTB,我们需要理财赚够20个. 理财是只能买入TDSU才可以获得收益.我们先上来直接把CTB全部换成TDSU ...
随机推荐
- 【51nod1678】lyk与gcd(莫比乌斯反演+枚举因数)
点此看题面 大致题意: 一个长度为\(n\)的数组,实现两种操作:单点修改,给定\(i\)求\(\sum_{j=1}^na_j[gcd(i,j)=1]\). 莫比乌斯反演 考虑推一推询问操作的式子: ...
- java之运算符的优先级
优先级 运算符 结合性 1 () [] 从左往右 2 ! +(正) -(负) ++ -- 从右往左 3 * / % 从左往右 4 << >> >>> 从左往 ...
- 如何用 Python 给照片换色
最近遇到了一个需求,就是对图片进行色彩风格转换,让一个物体可以以各种不同的色彩来呈现. 比如一个红色的苹果,我想把它转化成绿色,这可怎么办呢?本来想的解决方案是先识别边界,然后对边界内区域进行色彩替换 ...
- 前端笔记之React(一)初识React&组件&JSX语法
一.React项目起步配置 官网:https://reactjs.org/ 文档:https://reactjs.org/docs/hello-world.html 中文:http://react.c ...
- java获取下一天的日期
我们来看看Java怎么获取下一天的日期: 哈哈哈,开玩笑啦,这个只是个段子. "哪怕悲伤有1000种,快乐有1种就够了."
- fastdfs详细安装教程
前言 最近开始搞的项目涉及到 fastdfs,工欲善其事,必先利其器,于是我自己搭了一台 fastdfs 服务器.坑已经帮大家都踩过了.按照该教程100%能安装成功. 前期准备 一个centos7 一 ...
- MySql配置主从模式 Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.
今天在学习MyCat环境搭建的时候,在配置MySql的主从模式,发现slave在配置完毕后,配置的内容全部正确的情况下,报错了? Last_IO_Error: Fatal error: The sla ...
- C# 判断(Excel)文件是否已经打开
using System.IO; using System.Runtime.InteropServices; [DllImport("kernel32.dll")] publi ...
- JQ中的Ajax的封装
1.认识JQ中ajax的封装 jQ 对于ajax的封装有两层实现:$.ajax 为底层封装实现:基于 $.ajax ,分别实现了$.get 与$.post 的高层封装实现: 2.Ajax的底 ...
- 第三方库Mantle的源码解析
Mantle是一个用于简化Cocoa或Cocoa Touch程序中model层的第三方库.通常我们的应该中都会定义大量的model来表示各种数据结构,而这些model的初始化和编码解码都需要写大量的代 ...