题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2565

题意:中文题

思路:定义L[i],R[i]。表示以i为左端点/右端点时,最长回文串长度。那么答案就是L[i]+R[i]的最大值。问题转化为怎么求L[i],R[i]。我们通过用Manacher可以求出以i为中心的最长回文串半径。然后再通过暴力+剪枝的方法对于每一个i和对应的最长半径求更新L[i],R[i]。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=1e5+;
typedef long long int LL;
#define INF 0x3f3f3f3f
char str[MAXN],dstr[MAXN*];
int lenstr,lendstr,p[MAXN*],L[MAXN*],R[MAXN*],ans;
void manacher(){
memset(p,,sizeof(p));
memset(L,-,sizeof(L));
int id=,mx=;
for(int i=;i<lendstr;i++){
if(mx>i){
p[i]=min(p[*id-i],mx-i);
}
else{
p[i]=;
}
while(dstr[i-p[i]]==dstr[i+p[i]]){ //暴力匹配
p[i]++;
}
if(p[i]+i>mx){ //更新mx
mx=p[i]+i;
id=i;
}
}
}
void init(){ //变化原串
dstr[]='$';
dstr[]='#';
for(int i=;i<lenstr;i++){
dstr[i*+]=str[i];
dstr[i*+]='#';
}
lendstr=lenstr*+;
dstr[lendstr]='*';
}
int main()
{
while(~scanf("%s",str)){
lenstr=strlen(str);
init();
manacher();
ans=;
for(int i=;i<lendstr;i++){
p[i]--; L[i]=max(L[i],); R[i]=max(R[i],);
for(int j=p[i];j>;j--){
if(R[i+j]>=j){ //剪枝
break;
}
R[i+j]=j;
}
for(int j=p[i];j>;j--){
if(L[i-j]>=j){ //剪枝
break;
}
L[i-j]=j;
}
}
for(int i=;i<lendstr;i++){
if(L[i]>&&R[i]>){
ans=max(ans,L[i]+R[i]);
}
}
printf("%d\n",ans);
}
return ;
}

上面的代码跑了8S+。因为是暴力更新的L,R数组。所以复杂度几乎是O(n^2).考虑优化。我们可以知道在进行Manacher的时候可以知道当前已经覆盖的最远的位置mx和对应的id。那么当某个位置被mx第一次被覆盖之时,可以知道这个位置的R[i]一定是mx-id因为是第一次被覆盖到。所以一定是最长最优的。同理左边对应位置的L[i]也是。 意思就是在Manacher的过程顺便更新L[i],R[i].

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN = 1e5 + ;
typedef long long int LL;
#define INF 0x3f3f3f3f
char str[MAXN], dstr[MAXN * ];
int lenstr, lendstr, p[MAXN * ], R[MAXN * ], L[MAXN * ], ans;
void manacher(){
memset(R, -, sizeof(R));
memset(L, -, sizeof(L));
int id = , mx = ;
for (int i = ; i<lendstr; i++){
if (mx>i){
p[i] = min(p[ * id - i], mx - i);
R[i + p[i]] = max(R[i + p[i]], p[i]);
L[i - p[i]] = max(L[i - p[i]], p[i]);
}
else{
p[i] = ;
R[i] = max(R[i], p[i]);
L[i] = max(L[i], p[i]);
}
while (dstr[i - p[i]] == dstr[i + p[i]]){ //暴力匹配
R[i + p[i]] = max(R[i + p[i]], p[i]);
L[i - p[i]] = max(L[i - p[i]], p[i]);
p[i]++;
}
if (p[i] + i>mx){
mx = p[i] + i;
id = i;
}
}
}
void init(){
dstr[] = '$';
dstr[] = '#';
for (int i = ; i<lenstr; i++){
dstr[i * + ] = str[i];
dstr[i * + ] = '#';
}
lendstr = lenstr * + ;
dstr[lendstr] = '*';
}
int main()
{
while (~scanf("%s", str)){
lenstr = strlen(str);
init();
manacher();
ans = ;
for (int i = ; i<lendstr; i++){
if (L[i]>&&R[i]>){
ans = max(ans, L[i] + R[i]);
}
}
printf("%d\n", ans);
}
return ;
}

BZOJ 2565 回文串-Manacher的更多相关文章

  1. BZOJ 2342 回文串-Manacher

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2342 思路:先跑一遍Manacher求出p[i]为每个位置为中心的回文半径,因为双倍回文串 ...

  2. 回文树(回文自动机) - BZOJ 3676 回文串

    BZOJ 3676 回文串 Problem's Link: http://www.lydsy.com/JudgeOnline/problem.php?id=3676 Mean: 略 analyse: ...

  3. BZOJ 2565: 最长双回文串 [Manacher]

    2565: 最长双回文串 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1842  Solved: 935[Submit][Status][Discu ...

  4. BZOJ.2565.[国家集训队]最长双回文串(Manacher/回文树)

    BZOJ 洛谷 求给定串的最长双回文串. \(n\leq10^5\). Manacher: 记\(R_i\)表示以\(i\)位置为结尾的最长回文串长度,\(L_i\)表示以\(i\)开头的最长回文串长 ...

  5. bzoj 2565: 最长双回文串 manacher算法

    2565: 最长双回文串 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem. ...

  6. bzoj 相似回文串 3350 3103 弦图染色+manacher

    相似回文串 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 143  Solved: 68[Submit][Status][Discuss] Descr ...

  7. bzoj 3790 神奇项链 回文串 manacher|PAM

    LINK:神奇项链 存在两个操作:1. 一个操作可以生成所有形式的回文串 2.一个操作可以将两个串给合并起来 如果前缀和后缀相同还可以将其并起来. 多组询问 每次询问合成一个串所需最少多少次2操作. ...

  8. POJ 3974 回文串-Manacher

    题目链接:http://poj.org/problem?id=3974 题意:求出给定字符串的最长回文串长度. 思路:裸的Manacher模板题. #include<iostream> # ...

  9. 【回文串-Manacher】

    Manacher算法能够在O(N)的时间复杂度内得到一个字符串以任意位置为中心的回文子串.其算法的基本原理就是利用已知回文串的左半部分来推导右半部分. 转:http://blog.sina.com.c ...

随机推荐

  1. js中 map 遍历数组

    map 方法会迭代数组中的每一个元素,并根据回调函数来处理每一个元素,最后返回一个新数组.注意,这个方法不会改变原始数组. 在我们的例子中,回调函数只有一个参数,即数组中元素的值 (val 参数) , ...

  2. 【leetcode】 Interleaving String (hard)

    Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given:s1 = ...

  3. php 与 js 正则匹配

    php : <?php $str='<p>xxx</p>abc';$matches = array();if(preg_match('/<p>.*<\/ ...

  4. QtCreator 添加第三方头文件库文件路径

    打开工程名.pro文件 添加 INCLUDEPATH += $$PWD/../../Obelisk/thirdparty/prebuilt/include/LeapSDKOrion LIBS += - ...

  5. [Android Pro] root用户删除文件提示:Operation not permitted

    reference to : http://blog.csdn.net/evanbai/article/details/6187578 一些文件看上去可能一切正常,但当您尝试删除的时候,居然也会报错, ...

  6. [Android Pro] CountDownTimer倒计时

    定时执行在一段时候后停止的倒计时,在倒计时执行过程中会在固定间隔时间得到通知(译者:触发onTick方法),下面的例子显示在一个文本框中显示一个30s倒计时: new CountdownTimer(3 ...

  7. Linux iostat字段解析

    iostat主要用于监控系统设备的IO负载情况,iostat首次运行时显示自系统启动开始的各项统计信息,之后运行iostat将显示自上次运行该命令以后的统计信息.用户可以通过指定统计的次数和时间来获得 ...

  8. 忘记Mysql登录密码

    1,使用安全模式跳过验证: 如果 Mysql在运行,Kill掉. 如果mysqld_safe无法启动,可用管理员权限sudo . 2,本地登录: 启动Mysql 3,修改密码: 5.7之后, 更改密码 ...

  9. 51nod1006(lcs)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1006 题意:中文题诶- 思路:最长公共子序列模板题- 我们用d ...

  10. 无根树转有根树(dfs,tree)

    #include <bits/stdc++.h> #include <iostream> #include <queue> #include <stdio.h ...