[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的更多相关文章

  1. NABCD模型(猫咪记单词)

    项目需求分析与建议-NABCD模型(猫咪记单词)   N (Need 需求) 对于现在的学生,尤其是大学生来说,学习英语是一件非常重要的事.我们有四级六级托福雅思等各种各样的英语方面的考试.而学习英语 ...

  2. [TYVJ] P1423 GF和猫咪的玩具

    GF和猫咪的玩具 描述 Description GF同学和猫咪得到了一个特别的玩具,这个玩具由n个金属环(编号为1---n),和m条绳索组成,每条绳索连接两个不同的金属环,并且长度相同.GF左手拿起金 ...

  3. 猫咪记单词Beta版使用说明

    猫咪记单词Beta版使用说明 一.项目背景 英语四级考试.六级考试.托福.雅思等英语方面的考试是现在大学生必须面对的问题.同时因为学生对手机的使用越来越频繁,而且仅仅通过书本背诵单词又比较无聊坚持的时 ...

  4. Cal Cat for Mac(猫咪控日历工具)安装

    1.软件简介    Cal Cat 是 macOS 系统上一款猫咪控日历工具,可以将系统内置的日历工具美化成猫咪风格的日历,超级可爱的猫咪可是猫咪控的最爱了,喜欢的朋友快快用上吧. 加州猫是一个桌面集 ...

  5. 猫咪记单词——NABCD模型分析

    N ——Need 需求:学习英语是一件非常重要的事.面对各种各样的考试,学习英语,最重要的就是词汇量,背单词是提高词汇量的最直接的方法,但是单纯的背单词太单调.寻找一些合适的,更易于接受的背单词学习英 ...

  6. 算法 PK 猫咪 | 章鱼保罗后继竟然是只猫?

    简评:一只名叫阿喀琉斯(Achilles)的白猫一边小声叫着,一边慵懒地在分别插有俄罗斯和沙特阿拉伯国旗的食盆间踱步.这只看起来并不出众的小猫住在俄罗斯圣彼得堡埃尔米塔日博物馆(State Hermi ...

  7. TYVJ1423 GF和猫咪的玩具

    Description: GF同学和猫咪得到了一个特别的玩具,这个玩具由n个金属环(编号为1---n),和m条绳索组成,每条绳索连接两个不同的金属环,并且长度相同.GF左手拿起金属环L,猫咪右手(或者 ...

  8. COGS 1191. [Tyvj Feb11] 猫咪的进化

    ★   输入文件:neko.in   输出文件:neko.out   简单对比时间限制:1 s   内存限制:128 MB [背景] 对于一只猫咪来说,它是有九条命的.但是并不是所有的猫咪都是这样,只 ...

  9. CTF 两道web整数溢出题目(猫咪银行和ltshop)

    ①猫咪银行: (2018中科大hackgame) 一开始给十个CTB,而flag需要20个CTB,我们需要理财赚够20个. 理财是只能买入TDSU才可以获得收益.我们先上来直接把CTB全部换成TDSU ...

随机推荐

  1. JavaScript中如何判断数组类型

    前言 JavaScript中关于数组的判定问题,一直都是一个必须要掌握的点,那么,运用知识,如何判断一个类型是数组,就需要有对JavaScript使用有着深入的了解. 判断方法 一.Array.isA ...

  2. 关于Django

    Django项目的初始化配置包括 数据库配置 Django 配置 应用程序配置 关于项目和应用 应用是一个专门做某件事的网络应用程序——比如博客系统,或者公共记录的数据库,或者简单的投票程序 项目则是 ...

  3. electron应用生成exe程序并打包过程记录

    1.写好应用程序后,安装 electron-packager 在 package.json 文件中加入配置项目 "scripts": { "build": &q ...

  4. 洛谷 P1351 (枚举)

    ### 洛谷P1351 题目链接 ### 题目大意: 给你 n 个节点, n-1 条边的无向联通图.若定义(u,v)表示 u 与 v 点的最短距离,如果 (u,v)值为 2 ,则这两个点的点权之积(即 ...

  5. Protractor-引入Cucumber

    上一篇博文中我们已经在package.json中写入了cucumber依赖库,在执行 npm install 之后,cucumber就已经下载好了.接下来要做的是修改conf.js,请参考下图: 去年 ...

  6. IDEA maven设置配置

    IDEA Maven配置 1. 下载maven 下载地址 从官网上,下载一个压缩包,然后解压到任意的文件夹 Maven的安装必须需要jdk1.7+ 2. 环境变量设置 M2_HOME改为具体的路径,其 ...

  7. WPF DataGrid显示MySQL查询信息,且可删除、修改、插入 (原发布 csdn 2018-10-13 20:07:28)

    1.入行好几年了,工作中使用数据库几率很小(传统行业).借着十一假期回家机会,学习下数据库. 2.初次了解数据库相关知识,如果本文有误,还望告知. 3.本文主要目的,记录下wpf界面显示数据库信息,且 ...

  8. 百度Sitemap生成器

    今天用了两个小时, 为无限影视(https://www.88tv.org)开发了一个小工具, 用来生成baidu的sitemap.  方便用. 因为该电影站的视频内容详情网页的ID是自增长的,所以可以 ...

  9. 转:用 Python 一键分析你的上网行为, 看是在认真工作还是摸鱼

    简介 想看看你最近一年都在干嘛?看看你平时上网是在摸鱼还是认真工作?想写年度汇报总结,但是苦于没有数据?现在,它来了. 这是一个能让你了解自己的浏览历史的Chrome浏览历史记录分析程序,当然了,他仅 ...

  10. python:王思聪究竟上了多少次热搜?

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 朱小五 凹凸玩数据 PS:如有需要Python学习资料的小伙伴可以加 ...