题意

给定一个字符串 \(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. redis命令之 ----key(键)

    DEL DEL key [key ...] 删除给定的一个或多个 key . 不存在的 key 会被忽略. DUMP DUMP key 序列化给定 key ,并返回被序列化的值,使用 RESTORE  ...

  2. Word2Vector 中的 Hierarchical Softmax

    Overall Introduction 之前我们提过基于可以使用CBOW或者SKIP-GRAM来捕捉预料中的token之间的关系,然后生成对应的词向量. 常规做法是我们可以直接feed DNN进去训 ...

  3. CompletableFuture2

    public class CompletableFuture2 { public static void main(String[] args) throws InterruptedException ...

  4. 在.net中读写config文件的各种方法【转】

    今天谈谈在.net中读写config文件的各种方法. 在这篇博客中,我将介绍各种配置文件的读写操作. 由于内容较为直观,因此没有过多的空道理,只有实实在在的演示代码, 目的只为了再现实战开发中的各种场 ...

  5. c# 修改系统日期格式

    引用 using System.Runtime.InteropServices; [DllImport("kernel32.dll", EntryPoint = "Get ...

  6. MySql数据库中正则表达式

    命令 说明 ^ 在字符的开启处进行匹配 $ 在字符的末尾处进行匹配 . 匹配任何字符(包括回车和新行) [-.] 匹配括号内的任意单个字符 [m-n] 匹配m到n之间的任意单个字符,例如[0-9],[ ...

  7. Docker(一) - CentOS7中安装Docker - (视频教程)

    Docker的使用越来越多,安装也相对简单.本文使用视频的方式展示在CentOS7系统中安装Docker,本文更适合于准备入门学习Docker的童靴. 以下视频,请带上耳机开始聆听 (双击全屏播放) ...

  8. 超时空英雄传说2复仇魔神完全攻略&秘技

    ╓─╥───────────────────────────────────────────────────╥─╖ ║ ║ 超 時 空 英 雄 傳 說 2 ║ ║ ║ ║ --復 仇 魔 神-- ║ ...

  9. 如何搭建wordpress ,wecenter

    14.什么是LNMP架构 LNMP是指一组通常一起使用来运行动态网站或者服务器的自由软件名称首字母缩写.L指Linux,N指Nginx,M一般指MySQL,也可以指MariaDB,P一般指PHP,也可 ...

  10. maven 学习---Maven 构建配置文件

    什么是构建配置文件? 构建配置文件是一组配置的集合,用来设置或者覆盖 Maven 构建的默认配置.使用构建配置文件,可以为不同的环境定制构建过程,例如 Producation 和 Developmen ...