题意

给定一个字符串 \(s\) ,求一个子串 \(t\) 满足 \(t\) 是 \(s\) 的前缀、后缀且在除前缀后缀之外的地方出现过。

\(1 \leq |s| \leq 10^6\)

思路

\(\text{Z}\)算法是一个和 \(\text{Manacher}\)算法很像的字符串算法,功能是求出一个 \(z\) 数组,代表以 \(i\) 开头的后缀同整个串的 \(\text{lcp}\) 。

首先回顾一下 \(\text{Manacher}\)算法的流程。

int pos,r=0;
FOR(i,1,n) //字符串Manacher是在原字符串每两字符间插入'#'的字符串。
{
if(i<=r)p[i]=std::min(p[(pos<<1)-i],r-i+1);
else p[i]=1;
while(i-p[i]>=1&&i+p[i]<=n&&mnc[i-p[i]]==mnc[i+p[i]])p[i]++;
if(chk_max(r,i+p[i]-1))pos=i;
}

\(\text{Manacher}\)算法通过维护了目前扫到的最有端点,使得复杂度变成线性(可以发现把第 \(3,4\) 行替换成 p[i]=1; ,就变成了 \(O(n^2)\) 的暴力。

把它稍微变一下,就变成了\(\text{Z}\)算法。

z[1]=n;
int l,r=0;
FOR(i,2,n)
{
if(i<=r)z[i]=std::min(z[i-l+1],r-i+1);
else z[i]=0;
while(i+z[i]<=n&&str[i+z[i]]==str[1+z[i]])z[i]++;
if(chk_max(r,i+z[i]-1))l=i;
}

仍然是通过最右端点保证复杂度,和 \(\text{Manacher}\)完全一个道理。

对于这道题目而言,先考虑既是前缀又是后缀的限制,只需要对原串 \(str\) 求一下 \(z\) 数组,如果一个位置 \(i\) 满足 \(z[i]=|str|-i+1\) ,那么 \([i,|str|]\) 这个串就既是前缀又是后缀了。至于这个串还得在不是前缀不是后缀的地方出现过,我们可以对 \(z\) 数组求一个前缀最大值(除了 \(z[1]\) ,\(z[1]\) 没什么意义),这个前缀最大值就代表出现过的最长的前缀,因为你需要的串 \([i,|str|]\) 肯定也是个前缀,所以就看 \(|str|-i+1\) 是不是小于等于前缀最大值即可。

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
typedef long long ll;
const int N=1e6+5;
char str[N];int z[N];
int n; void get_z(char *str,int n)
{
z[1]=n;
int l,r=0;
FOR(i,2,n)
{
if(i<=r)z[i]=std::min(z[i-l+1],r-i+1);
else z[i]=0;
while(i+z[i]<=n&&str[i+z[i]]==str[1+z[i]])z[i]++;
if(chk_max(r,i+z[i]-1))l=i;
}
} int main()
{
scanf("%s",str+1);
n=strlen(str+1);
get_z(str,n);
int r=0;
FOR(i,2,n)
{
if(z[i]==n-i+1&&r>=n-i+1)
{
FOR(j,1,n-i+1)putchar(str[j]);
return 0;
}
chk_max(r,z[i]);
}
puts("Just a legend");
return 0;
}

Codeforces 126B Password(Z算法)的更多相关文章

  1. Codeforces 126B. Password(KMP,DP)

    Codeforces 126B. Password 题意:一个字符串,找出最长的子串t,它既是前缀又是后缀,还出现在中间.输出t,不存在则输出Just a legend. 思路:利用KMP算法处理出n ...

  2. CodeForces 126B Password

    题目链接:http://codeforces.com/problemset/problem/126/B 题目大意: 多组数据每组给定1个字符串S,问是否存在S的一个尽量长的子串,同时是S的前缀和后缀, ...

  3. Codeforces 126B. Password (KMP)

    <题目链接> 题目大意:给定一个字符串,从中找出一个前.中.后缀最长公共子串("中"代表着既不是前缀,也不是后缀的部分). 解题分析:本题依然是利用了KMP中next数 ...

  4. CodeForces - 1051E :Vasya and Big Integers(Z算法 & DP )

    题意:给定字符串S,A,B.现在让你对S进行切割,使得每个切割出来的部分在[A,B]范围内,问方案数. 思路:有方程,dp[i]=Σ dp[j]   (S[j+1,i]在合法范围内).    假设M和 ...

  5. Z算法

    Z算法 Z算法是一种用于字符串匹配的算法.此算法的核心在于\(z\)数组以及它的求法. (以下约定字符串下标从\(1\)开始) \(\bm z\)数组和Z-box 定义\(z\)数组:\(z_{a,i ...

  6. 【算法】字符串匹配之Z算法

    求文本与单模式串匹配,通常会使用KMP算法.后来接触到了Z算法,感觉Z算法也相当精妙.在以前的博文中也有过用Z算法来解决字符串匹配的题目. 下面介绍一下Z算法. 先一句话讲清楚Z算法能求什么东西. 输 ...

  7. Z算法板子

    给定一个串$s$, $Z$算法可以$O(n)$时间求出一个$z$数组 $z_i$表示$s[i...n]$与$s$的前缀匹配的最长长度, 下标从$0$开始 void init(char *s, int ...

  8. [Codeforces 364D]Ghd(随机算法+gcd)

    [Codeforces 364D]Ghd(随机算法) 题面 给出n个正整数,在其中选出n/2(向上取整)个数,要求这些数的最大公约数最大,求最大公约数的最大值 分析 每个数被选到的概率\(\geq \ ...

  9. 【Codeforces 126B】Password

    [链接] 我是链接,点我呀:) [题意] 给你一个字符串s 让你从中选出来一个字符串t 这个字符串t是s的前缀和后缀 且在除了前缀和后缀之外的中间部位出现过. 且要求t的长度最长. 让你输出这个字符串 ...

随机推荐

  1. linux bash 的基础语法

    示例均来自网络,附带有原始链接地址,自己练习整理发出,均测试可用 linux shell 基本语法 - 周学伟 - 博客园 https://www.cnblogs.com/zxouxuewei/p/6 ...

  2. 【LOJ#3146】[APIO2019]路灯(树套树)

    [LOJ#3146][APIO2019]路灯(树套树) 题面 LOJ 题解 考场上因为\(\text{bridge}\)某个\(\text{subtask}\)没有判\(n=1\)的情况导致我卡了\( ...

  3. Elastic 使用索引生命周期管理实现热温冷架构

    Elastic: 使用索引生命周期管理实现热温冷架构 索引生命周期管理 (ILM) 是在 Elasticsearch 6.6(公测版)首次引入并在 6.7 版正式推出的一项功能.ILM 是 Elast ...

  4. ASP.NET Core快速入门(第2章:配置管理)--学习笔记

    课程链接:http://video.jessetalk.cn/course/explore 良心课程,大家一起来学习哈! 任务9:配置介绍 命令行配置 Json文件配置 从配置文件文本到c#对象实例的 ...

  5. SpringBoot打可执行war包

    1. 主程序类: @SpringBootApplication public class Application extends SpringBootServletInitializer { @Ove ...

  6. RVZicsr指令集

    Riscv中每个硬件线程(hart)有4096个独立地址空间的状态寄存器.我们可以通过Zicsr指令读写csr寄存器.总共有6条csr读写指令,这些指令之前都在RV32I/RV64I基础指令集里面,在 ...

  7. [b0009] 玩Hadoop中碰到的各种错误

    1. Error: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class mp.filetest.WordCount2 ...

  8. Linux中断管理 (1)Linux中断管理机制【转】

    转自:https://www.cnblogs.com/arnoldlu/p/8659981.html 目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机 ...

  9. Rust中的所有权,引用和借用

    这个有意思,指针解释获新生!!! fn main() { let mut s = String::from("hello"); s.push_str(", world!& ...

  10. oracle_day1

    本节内容: 1:oracle的服务 2:oracle 11 G 的新功能 3:数据库的三大范式 1:oracle的服务 安装完oracle 想要使用oracle 必须要启动的两个服务. 要是还想要使用 ...