CF700E Cool Slogans 后缀自动机 + right集合线段树合并 + 树形DP
题目描述
给出一个长度为n的字符串s[1],由小写字母组成。定义一个字符串序列s[1....k],满足性质:s[i]在s[i-1] (i>=2)中出现至少两次(位置可重叠),问最大的k是多少,使得从s[1]开始到s[k]都满足这样一个性质。
发现 $s[1...k]$ 之间一定是互为后缀关系. 那么就可以建出后缀树,令 $dp_{u}$ 表示 $u$ 节点代表子串的答案
维护 $top_{u}$ 表示 $u$ 以及 $u$ 在后缀树的祖先中合法的且答案最大(答案相同则最短)的节点编号
$dp_{u}\Rightarrow dp_{top_{fa}}+1$ ,$fa$ 在 $u$ 中出现大于等于2次
$dp_{u}=1,top_{u}=top_{fa}$,$fa$ 在 $u$ 中仅出现 $1$ 次
#include<bits/stdc++.h>
#define maxn 400002
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
namespace tr
{
#define lson t[x].l
#define rson t[x].r
#define mid ((l+r)>>1)
int cnt;
struct Node { int l,r; }t[maxn*20];
void modify(int &x,int l,int r,int k)
{
if(!x) x=++cnt;
if(l==r) return;
if(k<=mid) modify(lson,l,mid,k);
else modify(rson,mid+1,r,k);
}
int merge(int u,int v)
{
if(!u||!v) return u+v;
int x=++cnt;
lson=merge(t[u].l,t[v].l);
rson=merge(t[u].r,t[v].r);
return x;
}
int query(int x,int l,int r,int L,int R)
{
if(!x) return 0;
if(l>=L&&r<=R) return 1;
int tmp=0;
if(L<=mid) tmp+=query(lson,l,mid,L,R);
if(R>mid) tmp+=query(rson,mid+1,r,L,R);
return tmp;
}
};
namespace SAM
{
char str[maxn];
int last,tot,n;
int trans[maxn][27],f[maxn],len[maxn],C[maxn],rk[maxn],top[maxn],dp[maxn],pos[maxn],rt[maxn];
void init() { last=tot=1; }
void extend(int c,int i)
{
int np=++tot,p=last;
len[np]=len[p]+1,last=np;
while(p&&!trans[p][c]) trans[p][c]=np,p=f[p];
if(!p) f[np]=1;
else
{
int q=trans[p][c];
if(len[q]==len[p]+1) f[np]=q;
else
{
int nq=++tot;
len[nq]=len[p]+1;
pos[nq]=pos[q];
memcpy(trans[nq],trans[q],sizeof(trans[q]));
f[nq]=f[q], f[np]=f[q]=nq;
while(p&&trans[p][c]==q) trans[p][c]=nq,p=f[p];
}
}
pos[np]=i;
tr::modify(rt[last],1,n,i);
}
void prepare()
{
int i,j;
init();
scanf("%d%s",&n,str+1);
for(i=1;i<=n;++i) extend(str[i]-'a',i);
for(i=1;i<=tot;++i) ++C[len[i]];
for(i=1;i<=tot;++i) C[i]+=C[i-1];
for(i=1;i<=tot;++i) rk[C[len[i]]--]=i;
for(i=tot;i>1;--i)
{
int u=rk[i];
rt[f[u]]=tr::merge(rt[f[u]],rt[u]);
}
}
void calc()
{
int i,j,ans=1;
for(i=2;i<=tot;++i)
{
int u=rk[i],ff=f[rk[i]];
if(ff==1) { top[u]=u,dp[u]=1; continue; }
if(tr::query(rt[top[ff]],1,n,pos[u]-len[u]+len[top[ff]],pos[u]-1))
top[u]=u,dp[u]=dp[top[ff]]+1;
else
top[u]=top[ff];
ans=max(ans,dp[u]);
}
printf("%d\n",ans);
}
};
int main()
{
//msetIO("input");
SAM::prepare();
SAM::calc();
return 0;
}
CF700E Cool Slogans 后缀自动机 + right集合线段树合并 + 树形DP的更多相关文章
- CF1037H Security 后缀自动机 + right集合线段树合并 + 贪心
题目描述: 给定一个字符串 $S$ 给出 $Q$ 个操作,给出 $L,R,T$,求出字典序最小的 $S_{1}$ 为 $S[L...R]$的子串,且 $S_{1}$ 的字典序严格大于 $T$. 输出这 ...
- [BJWC2018]Border 的四种求法(后缀自动机+链分治+线段树合并)
题目描述 给一个小写字母字符串 S ,q 次询问每次给出 l,r ,求 s[l..r] 的 Border . Border: 对于给定的串 s ,最大的 i 使得 s[1..i] = s[|s|-i+ ...
- 【codeforces666E】Forensic Examination 广义后缀自动机+树上倍增+线段树合并
题目描述 给出 $S$ 串和 $m$ 个 $T_i$ 串,$q$ 次询问,每次询问给出 $l$ .$r$ .$x$ .$y$ ,求 $S_{x...y}$ 在 $T_l,T_{l+1},...,T_r ...
- CF547E Milk and Friends(AC自动机的fail指针上建主席树 或 广义后缀自动机的parent线段树合并)
What-The-Fatherland is a strange country! All phone numbers there are strings consisting of lowercas ...
- LOJ #2537. 「PKUWC 2018」Minimax (线段树合并 优化dp)
题意 小 \(C\) 有一棵 \(n\) 个结点的有根树,根是 \(1\) 号结点,且每个结点最多有两个子结点. 定义结点 \(x\) 的权值为: 1.若 \(x\) 没有子结点,那么它的权值会在输入 ...
- 【CF700E】Cool Slogans 后缀自动机+线段树合并
[CF700E]Cool Slogans 题意:给你一个字符串S,求一个最长的字符串序列$s_1,s_2,...,s_k$,满足$\forall s_i$是S的子串,且$s_i$在$s_{i-1}$里 ...
- 模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合)
模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合) Code: #include <bits/stdc++.h> using namespace std; #define ...
- Codeforces.700E.Cool Slogans(后缀自动机 线段树合并 DP)
题目链接 \(Description\) 给定一个字符串\(s[1]\).一个字符串序列\(s[\ ]\)满足\(s[i]\)至少在\(s[i-1]\)中出现过两次(\(i\geq 2\)).求最大的 ...
- 洛谷P4770 [NOI2018]你的名字 [后缀自动机,线段树合并]
传送门 思路 按照套路,直接上后缀自动机. 部分分:\(l=1,r=|S|\) 首先把\(S\)和\(T\)的后缀自动机都建出来. 考虑枚举\(T\)中的右端点\(r\),查询以\(r\)结尾的串最长 ...
随机推荐
- Docker安装及部署实例.Net Core
1.什么是Docker Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱 ...
- XML读写工具类
摘要:①读取XML文件,生成pojo对象:②将对象信息保存到xml中. 步骤: ①新建一个普通的java类BasePage: package com.test.selenium.pages; impo ...
- EditPlus配色方案
找到配置文件:editplus_u.ini配置文件 [Options] Placement=2C00000002000000030000000083FFFF0083FFFFFFFFFFFFFFFFFF ...
- Smashing Nodejs 读书笔记(一)
了不起的Node.js:将JavaScript进行到底 书名:SMASHING Node.js : JavaScript Everywhere 原作者:(美)劳奇 Rauch.G 译者:赵静 出版日期 ...
- oracle--少见操作、如何调整dos窗口大小、字符集设置
如何调整dos窗口大小 1.set linesize 400; 2.右键 --默认值 断开.连接 disconn ; conn ww/ww; 关于字符集 操作系统环境变量针对语言项设置有几个,我经常设 ...
- python字典-基础
一.解释 像列表一样,“字典”是许多值的集合.但不像列表的下标,字典的索引可以 使用许多不同数据类型,不只是整数.字典的索引被称为“键”,键及其关联的值 称为“键-值”对. 二.列表创建方式 1. I ...
- WPF ControlTemplate
ControlTemplate:控件模板,顾名思义也就是定制特定的控件供公共调用,有点类似WinForm中对一些通用控件进行重写使用. ControlTemplate:控件模板主要有两个重要属性:Vi ...
- docker相关知识
DevOps 是一个完整的面向IT运维的工作流,以 IT 自动化以及持续集成(CI).持续部署(CD)为基础,来优化程式开发.测试.系统运维等所有环节.突出重视软件开发人员和运维人员的沟通合作,通过自 ...
- SQL SERVER 数据库跨服务器备份
原文:https://www.cnblogs.com/jaday/p/6088200.html 需求介绍:每天备份线上正式库并且把备份文件复制到测试服务器,测试服务器自动把数据库备份文件还原. 方案介 ...
- .linux基础命令三
一. 两台服务器免密登录: 1. 生成密钥 ssh-keygen的命令手册,通过”man ssh-keygen“命令查看指令: 通过命令”ssh-keygen -t rsa“创建一对密匙,包括公匙和私 ...