题意

给定一个字符串 \(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. Gitlab 备份还原/迁移

    Gitlab 备份还原 备份数据:通过命令进行备份操作 gitlab-rake gitlab:backup:create ... [DISABLED] Creating backup archive: ...

  2. .net core 3.0中的Json API

    在.net core 3.0中,内置了一套新的json api,主要用于去除asp.net core对json.net的依赖,同时也提供了更好的性能(直接处理 UTF-8,而无需转码到 UTF-16) ...

  3. GSOAP服务卡住?

    很久以前参考了https://www.genivia.com/doc/soapdoc2.html 中的一段: How to Create a Multi-Threaded Stand-Alone Se ...

  4. AT+CNUM获取不到手机号

    原因是卡商没有写入SIM卡 解决办法 手动写入 1. 先确认SIM卡的本机号码 2. 选择电话本存储 /* AT+CPBS Select phonebook memory storage " ...

  5. ios 点击webview获取图片url (js交互)

    加手势 -(void)handleSingleTap:(UITapGestureRecognizer *)sender { CGPoint pt = [sender locationInView:_c ...

  6. flink 实现三角枚举EnumTriangles算法详解

    1.三角枚举,从所有无向边对中找到相互连接的三角形 /** * @Author: xu.dm * @Date: 2019/7/4 21:31 * @Description: 三角枚举算法 * 三角枚举 ...

  7. 2.InfluxDB-InfluxQL基础语法教程--目录

    本文翻译自官网,官方文档地址:(https://docs.influxdata.com/influxdb/v1.7/query_language/data_exploration/) InfluxQL ...

  8. 互联网渗透测试之Wireshark的高级应用

    互联网渗透测试之Wireshark的高级应用 1.1说明 在本节将介绍Wireshark的一些高级特性 1.2. "Follow TCP Stream" 如果你处理TCP协议,想要 ...

  9. LGBMClassifier参数

    本文链接:https://blog.csdn.net/starmoth/article/details/845867091.boosting_type=‘gbdt’# 提升树的类型 gbdt,dart ...

  10. python开发微信公众号SDK选择

    1.wechat-sdk sudo pip install wechat-sdk 文档地址:  http://ww2.wechat-python-sdk.com/ 2.wechat sudo pip ...