题目链接

题目分析

题目要求我们构造一个最长的 \(T\) 序列,我们首先从每个 \(T_i\) 入手,思考如何安排才能合法。

容易观察到对于每个 \(T_i\),合法的 \(T_{i-1}\) 有两种方式构造,要么直接为上一个字符串左右端点平移得到,要么找到另外一个等于 \(T_i\) 的子串再平移得到,这似乎启发我们使用 SAM 对 endpos 集合进行维护,但思考后发现这似乎不容易实现,于是我们转换思考方式。

着眼于构造方式而非字符串,由于每次从大到小构造时,如果没有重复子串,构造过程相当于向左移动一个单位并且长度缩短,我们可以从中得到一个答案的下界:\(\left\lfloor\dfrac{|s|}{2}\right\rfloor\)。

如果加上重复子串呢,可以发现从右到左地更换匹配位置答案只会变坏,而从左到右则就相当于如果原先长度还没减完就移动到了左端点,现在从左往右更换则为其“续命”,可以让他继续移动,并且后面构造出的 \(T\) 也会在原串中出现至少两次,可以继续“续命”。

结合上述讨论,我们可以将 \(T\) 数组分为两种情况,分别为一段出现两次,一段出现一次与只出现一次的,后者答案的最大值即为 \(\left\lfloor\dfrac{|s|}{2}\right\rfloor\)。前者由于必然经过一个出现过两次的字符串,我们可以用 SAM 在此处统计,每个左右端点分别为 \(l\),\(r\),出现过两次的字符串对答案的贡献为 \(r-l+1+ \left\lfloor\dfrac{n-r}{2}\right\rfloor\)。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define ll long long
#define N 1500005
using namespace std;
string s[N];
int len[N<<1],fa[N<<1],nex[N<<1][27];
int head[N<<1],ne[N<<1],to[N<<1],en[N<<1],sum[N<<1];
int last=1,tot=1,e,ans=0,le;
void insert(int num){
int p=last,np=++tot;last=np;
len[np]=len[p]+1;
en[np]=en[p]+1;sum[np]=1;
for(;p && !nex[p][num];p=fa[p])nex[p][num]=np;
if(!p) fa[np]=1;
else{
int q=nex[p][num];
if(len[q]==len[p]+1) fa[np]=q;
else{
int clone=++tot;len[clone]=len[p]+1;
fa[clone]=fa[q];fa[q]=fa[np]=clone;
for(int i=1;i<=26;i++) nex[clone][i]=nex[q][i];
for(;p && nex[p][num]==q;p=fa[p]) nex[p][num]=clone;
}
}
}
void addedg(int u,int v){
to[++e]=v;ne[e]=head[u];head[u]=e;
to[++e]=u;ne[e]=head[v];head[v]=e;
}
void dfs(int x,int fa){
if(!en[x]) en[x]=0x3f3f3f3f;
for(int i=head[x];i;i=ne[i]){
int v=to[i];
if(v==fa) continue;
dfs(v,x);en[x]=min(en[x],en[v]);sum[x]+=sum[v];
}
if(sum[x]>1)ans=max(ans,len[x]+(le-en[x])/2);
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>s[i];
for(int i=1;i<=n;i++){
le=s[i].length();
for(int j=0;j<le;j++) insert(s[i][j]-'a'+1);
for(int j=2;j<=tot;j++){
addedg(j,fa[j]);
}
dfs(1,0);
ans=max(ans,le/2);
cout<<ans<<endl;
ans=0;
for(int j=1;j<=e;j++)to[j]=ne[j]=0;
for(int j=1;j<=tot;j++) head[j]=0;
for(int j=1;j<=tot;j++) fa[j]=len[j]=sum[j]=en[j]=0;
for(int j=1;j<=tot;j++) for(int k=1;k<=26;k++) nex[j][k]=0;
tot=1;last=1;e=0;
} }

P8368 [LNOI2022] 串 题解的更多相关文章

  1. cojs 简单的01串 题解报告

    题意显然是求n位二进制串中不大于其逆序串,取反串,逆序取反串的所有串按字典序排序后的第k个 由于n很小,k很大所以我们可以考虑逐位确定 问题转化为了求方案数,这显然是可以用数位DP做的 设f[len] ...

  2. BZOJ4755: [JSOI2016]扭动的回文串——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4755 JYY有两个长度均为N的字符串A和B. 一个“扭动字符串S(i,j,k)由A中的第i个字符到 ...

  3. BZOJ2565:最长双回文串——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2565 题目大意: 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(ab ...

  4. 淘淘蓝蓝的CSP-S神妙膜你赛2-淘淘蓝蓝喜欢01串 题解

    问题简述 给定\(n\)个盒子,每个盒子的容器为\(b[i]\),里面装有\(a[i]\)个物品.今有\(q\)组询问,每组询问给出一个正整数\(k(k<=n)\),已知一个盒子里的一件物品转移 ...

  5. bzoj4503: 两个串 bitset

    目录 题目链接 题解 代码 题目链接 bzoj4503: 两个串 题解 暴一发bitset f[i][j] 表示 S[1..i] 是否有个后缀能匹配 T[1..j] 那么假设 S[i+1] 能匹配 T ...

  6. Codeforces Round #410 (Div. 2) 题解 【ABCD】

    A 题意:问你恰好修改一个字符,能不能使得字符串变成回文串 题解:显然直接for一遍,如果长度为偶数,那么不一样的必须是1个:如果长度为奇数,那么不一样的也可以是0个 #include<bits ...

  7. 【Atcoder】AGC027 题解

    A - Candy Distribution Again 大意:有x个糖给n个小朋友,必须分完,小朋友得到糖数为一个确切值的时候小朋友会开心,求最多的开心数 题解 直接排序然后贪心分,如果分到最后一个 ...

  8. SPOJ LCS2 - Longest Common Substring II 后缀自动机 多个串的LCS

    LCS2 - Longest Common Substring II no tags  A string is finite sequence of characters over a non-emp ...

  9. [LeetCode] 132. 分割回文串 II

    题目链接 : https://leetcode-cn.com/problems/palindrome-partitioning-ii/ 题目描述: 给定一个字符串 s,将 s 分割成一些子串,使每个子 ...

  10. Manacher || P4555 [国家集训队]最长双回文串 || BZOJ 2565: 最长双回文串

    题面:P4555 [国家集训队]最长双回文串 题解:就.就考察马拉车的理解 在原始马拉车的基础上多维护个P[i].Q[i]数组,分别表示以i结尾最长回文子串的长度和以i开头的最长回文子串的长度 然后就 ...

随机推荐

  1. 教师节专题:AI互动课来了,即构方案助推在线教育创新升级

    打开热门综艺,乘风破浪的姐姐们告诉你"用瓜瓜龙英语给孩子启蒙":走出家门,电梯口.公交站的大幅广告跟你说"2-8岁上斑马". 如果说去年的AI互动课还是浮于媒体 ...

  2. 图像处理_Retinex图像增强

    单尺度SSR (Single Scale Retinex) 图像 S ( x , y ) S(x,y) S(x,y)分解为两个不同的图像:反射图像 R ( x , y ) R(x,y) R(x,y), ...

  3. Spring 的依赖注入

    Spring 的依赖注入 @ 目录 Spring 的依赖注入 每博一文案 1. 依赖注入 1.1 构造注入 1.1.1 通过参数名进行构造注入 1.1.2 通过参数的下标,进行构造注入 1.1.3 不 ...

  4. Gin中间件开发

    Gin是一个用Go语言编写的Web框架,它提供了一种简单的方式来创建HTTP路由和处理HTTP请求.中间件是Gin框架中的一个重要概念,它可以用来处理HTTP请求和响应,或者在处理请求之前和之后执行一 ...

  5. 【Unity3D】平面光罩特效

    1 前言 ​ 屏幕深度和法线纹理简介中对深度和法线纹理的来源.使用及推导过程进行了讲解,激光雷达特效中讲述了一种重构屏幕像素点世界坐标的方法,本文将沿用激光雷达特效中重构像素点世界坐标的方法,实现平面 ...

  6. 微服务集成RabbitMq保姆级教程

    本文通过简单的示例代码和说明,让读者能够了解微服务如何集成RabbitMq 之前的教程 https://www.cnblogs.com/leafstar/p/17641358.html 在这里我将介绍 ...

  7. 三维模型OSGB格式轻量化压缩必要性分析

    三维模型OSGB格式轻量化压缩必要性分析 三维模型是计算机图形学和视觉效果等领域的重要应用之一.然而,由于三维模型通常包含大量的几何信息.纹理信息和其他元素,导致其占用的存储空间和计算资源非常巨大.为 ...

  8. PHP写一个 Api接口需要注意哪些?考虑哪些?

    随着互联网的飞速发展,前后端分离的开发模式越来越流行.编写一个稳定.可靠和易于使用的 API 接口是现代互联网应用程序的关键.本文将介绍在使用 thinkphp6 框架开发 API 接口时需要注意的要 ...

  9. elasticsearch wildcard 慢查询原因分析(深入到源码!!!)

    大家好,我是蓝胖子,前段时间线上elasticsearch集群遇到多次wildcard产生的性能问题, elasticsearch wildcard 一直是容易引发elasticsearch 容易宕机 ...

  10. C# Wke例子 -- WebUI登录窗口

    概述 Wke介绍: http://blog.csdn.net/sabrecode/article/details/78145938 用Wke做了一个登录窗口, webui比较特殊. 因为它就是一个超文 ...