POJ3974 Palindrome Manacher 最长回文子串模板
这道题可以$O(nlogn)$,当然也可以$O(n)$做啦$qwq$
$O(nlogn)$的思路是枚举每个回文中心,通过哈希预处理出前缀和后缀哈希值备用,然后二分回文串的长度,具体的就是判断在长度范围内,前缀哈希值和后缀哈希值是否相等。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll unsigned long long
#define R register int
using namespace std;
namespace Fread {
static char B[<<],*S=B,*D=B;
#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
}
}using Fread::g;
const int B=,N=;
int t,ans;
ll h1[N],h2[N],p[N];
char s[N];
inline ll H1(int l,int r) {return h1[r]-h1[l-]*p[r-l+];}
inline ll H2(int l,int r) {return h2[l]-h2[r+]*p[r-l+];}
signed main() {
#ifdef JACK
freopen("NOIPAK++.in","r",stdin);
#endif
p[]=; for(R i=;i<=N-;++i) p[i]=p[i-]*B;
while() { ans=; ++t;
scanf("%s",s+); R len=strlen(s+);
if(len==&&s[]=='E'&&s[]=='N'&&s[]=='D') break;
for(R i=;i<=len;++i) h1[i]=h1[i-]*B+(s[i]^)+;
for(R i=len;i>=;--i) h2[i]=h2[i+]*B+(s[i]^)+;
for(R p=;p<=len;++p) {
register int l=,r=min(p-,len-p);
while(l<r) {
register int md=l+r+>>;
if(H1(p-md,p-)==H2(p+,p+md)) l=md;
else r=md-;
} ans=max(ans,l*+);
l=,r=min(p-,len-p+);
while(l<r) {
register int md=l+r+>>;
if(H1(p-md,p-)==H2(p,p+md-)) l=md;
else r=md-;
} ans=max(ans,l*);
} printf("Case %d: %d\n",t,ans);
}
}
还有一个$Manacher$算法,可以在$O(n)$时间里解决这个问题,详见这位大佬的博客
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define R register int
using namespace std;
namespace Fread {
static char B[<<],*S=B,*D=B;
#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
}
}using Fread::g;
const int N=;
char s[N<<],str[N<<];
int len[N<<],l;
inline void getstr() {
R k=; str[k]='$';
for(R i=;i<=l;++i) str[++k]='#',str[++k]=s[i];
str[++k]='#'; l=k;
}
inline void Manacher() {
getstr(); R mx=,id;
for(R i=;i<l;++i) {
if(mx>i) len[i]=min(len[*id-i],mx-i);//先找对称的位置,和右边界取一个min
else len[i]=;//不包含直接设为1
while(str[i+len[i]]==str[i-len[i]]) ++len[i];//暴力匹配
if(len[i]+i>mx) mx=len[i]+i,id=i;//更新mx和id
}
}
signed main() {
#ifdef JACK
freopen("NOIPAK++.in","r",stdin);
#endif
R t=; while() { memset(len,,sizeof(len)); ++t;
scanf("%s",s); l=strlen(s);
if(l==&&s[]=='E'&&s[]=='N'&&s[]=='D') break;
Manacher(); R ans=; for(R i=;i<l;++i) ans=max(ans,len[i]);
printf("Case %d: %d\n",t,ans-);
}
}
洛谷上也有$manacher$的模板,可以水一下;
2019.06.10
POJ3974 Palindrome Manacher 最长回文子串模板的更多相关文章
- poj3974 Palindrome(Manacher最长回文)
之前用字符串hash+二分过了,今天刚看了manacher拿来试一试. 这manacher也快太多了%%% #include <iostream> #include <cstring ...
- POJ 3974 Palindrome(最长回文子串)
题目链接:http://poj.org/problem?id=3974 题意:求一给定字符串最长回文子串的长度 思路:直接套模板manacher算法 code: #include <cstdio ...
- Ural 1297 Palindrome 【最长回文子串】
最长回文子串 相关资料: 1.暴力法 2.动态规划 3.中心扩展 4.Manacher法 http://blog.csdn.net/ywhorizen/article/details/6629268 ...
- Manacher 最长回文子串。
最长回文子串就是一个字符串的一个子串,他从左往右读和从右往左读是一样的. 可以用 Manacher 算法来求,他的复杂度是 O(n) . 可以看这篇文章 http://blog.csdn.net/yw ...
- 后缀数组 - 求最长回文子串 + 模板题 --- ural 1297
1297. Palindrome Time Limit: 1.0 secondMemory Limit: 16 MB The “U.S. Robots” HQ has just received a ...
- manacher 最长回文子串
确定当前已知能匹配到的最长处,看是否要更新最长 #include <bits/stdc++.h> using namespace std; const int N = 210005; in ...
- manacher最长回文子串
https://www.luogu.org/blog/codesonic/manacheralgorithm 先放上洛谷的链接,毕竟讲的真好 两道例题 luogu4555 SP7586 inline ...
- Palindrome - POJ 3974 (最长回文子串,Manacher模板)
题意:就是求一个串的最长回文子串....输出长度. 直接上代码吧,没什么好分析的了. 代码如下: ================================================= ...
- 最长回文子串——manacher
最长回文子串--Manacher 算法 (原版的博主的代码都是用py写的,这里改成c++) c++ 算法 字符串处理 0. 问题定义 最长回文子串问题:给定一个字符串,求它的最长回文子串长度. 如果一 ...
随机推荐
- L1-039 古风排版(20 分)
中国的古人写文字,是从右向左竖向排版的.本题就请你编写程序,把一段文字按古风排版. 输入格式: 输入在第一行给出一个正整数N(<100),是每一列的字符数.第二行给出一个长度不超过1000的非空 ...
- P1364 医院设置
题目描述 设有一棵二叉树,如图: 其中,圈中的数字表示结点中居民的人口.圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为l.如上 ...
- Poj 2017 Speed Limit(水题)
一.Description Bill and Ted are taking a road trip. But the odometer in their car is broken, so they ...
- CentOS6和CentOS7服务开机启动
CentOS 6和CentOS 7都可以定义开机启动哪些服务,但CentOS 6的命令是chkconfig,CentOS 7是systemctl. 本文将介绍两种命令的实现方式. 一.CentOS 6 ...
- 第 七 课 go的运算符
http://www.runoob.com/go/go-operators.html 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 其他运算符 返回变量存储地址: & 指针变量: ...
- Linux中发布项目的一些命令笔记
记一下,Linux中发布项目的一些难记的命令: .安装jdk a.检测是否安装了jdk 运行java -version b.若有需要将其卸载 c.查看安装那些jdk rpm -qa | grep ja ...
- Codeforces 1107G Vasya and Maximum Profit 线段树最大子段和 + 单调栈
Codeforces 1107G 线段树最大子段和 + 单调栈 G. Vasya and Maximum Profit Description: Vasya got really tired of t ...
- oracle上课 学习2 oracle 游标 存储过程 有用
1.1. 训练描述 使用游标,打印emp中20号部门的所有员工的信息 操作步骤答案 declare cursor c_emp is select * from emp where deptno=10 ...
- Linux 启动顺序
Linux 启动顺序:1. BIOS自检2. 运行系统内核并检测硬件3. 运行系统的第一个进程init4. init读取系统引导配置文件/etc/inittab中的信息进行初始化 ...
- hbase各种遍历查询shell语句 包含过滤组合条件
import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Li ...