POJ 3974 最长回文字串(manacher算法)
题意:给出一个字符串,求出最长回文字串。
思路:一开始我直接上了后缀数组DC3的解法,然后MLE了。看了DISCUSS发现还有一种计算回文字串更加优越的算法,就是manacher算法。就去学习了一下,
/************************以下转自http://funnyxj.blog.163.com/blog/static/20459016020127514231538/********************/
这个算法要解决的就是一个字符串中最长的回文子串有多长。这个算法可以在O(n)的时间复杂度内既线性时间复杂度的情况下,求出以每个字符为中心的最长回文有多长,
这个算法有一个很巧妙的地方,它把奇数的回文串和偶数的回文串统一起来考虑了。这一点一直是在做回文串问题中时比较烦的地方。这个算法还有一个很好的地方就是充分利用了字符匹配的特殊性,避免了大量不必要的重复匹配。
算法大致过程是这样。先在每两个相邻字符中间插入一个分隔符,当然这个分隔符要在原串中没有出现过。一般可以用‘#’分隔。这样就非常巧妙的将奇数长度回文串与偶数长度回文串统一起来考虑了(见下面的一个例子,回文串长度全为奇数了),然后用一个辅助数组P记录以每个字符为中心的最长回文串的信息。P[id]记录的是以字符str[id]为中心的最长回文串,当以str[id]为第一个字符,这个最长回文串向右延伸了P[id]个字符。
原串: w aa bwsw f d
新串: # w# a # a # b# w # s # w # f # d #
辅助数组P: 1 2 1 2 3 2 1 2 1 2 1 4 1 2 1 2 1 2 1
这里有一个很好的性质,P[id]-1就是该回文子串在原串中的长度(包括‘#’)。如果这里不是特别清楚,可以自己拿出纸来画一画,自己体会体会。当然这里可能每个人写法不尽相同,不过我想大致思路应该是一样的吧。
好,我们继续。现在的关键问题就在于怎么在O(n)时间复杂度内求出P数组了。只要把这个P数组求出来,最长回文子串就可以直接扫一遍得出来了。
由于这个算法是线性从前往后扫的。那么当我们准备求P[i]的时候,i以前的P[j]我们是已经得到了的。我们用mx记在i之前的回文串中,延伸至最右端的位置。同时用id这个变量记下取得这个最优mx时的id值。(注:为了防止字符比较的时候越界,我在这个加了‘#’的字符串之前还加了另一个特殊字符‘$’,故我的新串下标是从1开始的)
/********************************************************************************************************************************/
CODE:
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Max 2505
#define FI first
#define SE second
#define ll long long
#define PI acos(-1.0)
#define inf 0x3fffffff
#define LL(x) ( x << 1 )
#define bug puts("here")
#define PII pair<int,int>
#define RR(x) ( x << 1 | 1 )
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )
#define N 2000055
using namespace std; char s[N] ;
char str[N] ;
int rad[N] ;
int manacher () {
int len = strlen(s) ;
int max = 0;
str[0] = '$';
str[1] = '#';
int i = 0 ;
for (; i < len; i++) {
str[i * 2 + 2] = s[i];
str[i * 2 + 3] = '#';
}
str[2 * len + 2] = 0;
for (int i = 1; i < 2 * len + 2 ; i++) {
rad[i] = 0;
}
int id = 0;
for (i = 1; i < 2 * len + 2; i++) {
if (max > i)
rad[i] = min(rad[2 * id - i], rad[id] + id - i) ;
else
rad[i] = 1 ;
while (str[i + rad[i]] == str[i - rad[i]])
rad[i] ++ ;
if (rad[i] + i > max) {
max = rad[i] + i;
id = i;
}
}
int mx = 0;
for (i = 1; i < 2 * len + 2 ; i++) {
if (mx < rad[i] - 1)
mx = rad[i] - 1;
}
return mx;
} int main() {
int ca = 0 ;
while(scanf("%s",s) != EOF) {
if(strcmp(s , "END") == 0)break ;
printf("Case %d: " , ++ ca) ;
printf("%d\n",manacher()) ;
}
return 0 ;
}
POJ 3974 最长回文字串(manacher算法)的更多相关文章
- 最长回文字串——manacher算法
时间复杂度:O(n) 参考:https://segmentfault.com/a/1190000003914228 1.问题定义 最长回文子串问题:给定一个字符串,求它的最长回文子串长度. 如果一个字 ...
- Hdu 3068 最长回文字串Manacher算法
题目链接 最长回文 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- Palindrome(最长回文串manacher算法)O(n)
Palindrome Time Limit:15000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit ...
- poj_1974,最长回文字串manacher
时间复杂度为O(n),参考:http://bbs.dlut.edu.cn/bbstcon.php?board=Competition&gid=23474 #include<iostrea ...
- 求字符串的最长回文字串 O(n)
昨天参加了某公司的校园招聘的笔试题,做得惨不忍睹,其中就有这么一道算法设计题:求一个字符串的最长回文字串.我在ACM校队选拔赛上遇到过这道题,当时用的后缀数组AC的,但是模板忘了没写出代码来. 回头我 ...
- hihocoder 第一周 最长回文字串
题目1 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程 ...
- 最长回文子串—Manacher 算法 及 python实现
最长回文子串问题:给定一个字符串,求它的最长回文子串长度.如果一个字符串正着读和反着读是一样的,那它就是回文串. 给定一个字符串,求它最长的回文子串长度,例如输入字符串'35534321',它的最 ...
- HiHo 1032 最长回文子串 (Manacher算法求解)
/** * 求解最长回文字串,Manacher算法o(n)求解最长回文子串问题 **/ #include<cstdio> #include<cstdlib> #include& ...
- luoguP4555 [国家集训队]最长双回文串 manacher算法
不算很难的一道题吧.... 很容易想到枚举断点,之后需要处理出以$i$为开头的最长回文串的长度和以$i$为结尾的最长回文串的长度 分别记为$L[i]$和$R[i]$ 由于求$R[i]$相当于把$L[i ...
随机推荐
- java--方法和成员的继承,访问
//在调用方法的时候,不是看句柄是哪一个类,而应该看对象是属于哪一个类的,属于哪一个类的,就调用哪一个类的成员和方法. //子类可以添加自己的新方法,但是子类对象的引用赋值给父类句柄之后,不能使用父类 ...
- C#版二维码生成器附皮肤下载
原文 C#版二维码生成器附皮肤下载 前言 本文所使用的二维码生成代码是谷歌开源的条形码图像处理库完成的,c#版的代码可去https://code.google.com/p/zxing/download ...
- Linux解压乱码
.向系统添加windows下的字符编码: sudo vim /var/lib/locales/supported.d/local 添加一下编码: zh_CN.GBK GBK zh_CN.GB2312 ...
- 基于visual Studio2013解决算法导论之007优先队列(堆实现)
题目 优先队列 解决代码及点评 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #in ...
- 基于visual Studio2013解决算法导论之001插入排序
题目 插入排序 解决代码及点评 #include <stdio.h> #include <time.h> #include <stdlib.h> void ...
- 数据结构读书笔记(三)(C语言)
栈 顺序实现: 存储结构: #define STACK_INIT_SIZE 10 // 存储空间初始分配量 #define STACK_INCREMENT 2 // 存储空间分配增量 struct S ...
- ARMv8 Linux内核head.S源码分析
ARMv8Linux内核head.S主要工作内容: 1. 从el2特权级退回到el1 2. 确认处理器类型 3. 计算内核镜像的起始物理地址及物理地址与虚拟地址之间的偏移 4. 验证设备树的地址是否有 ...
- 跟着鬼哥学so改动,一,准备篇
图/文 听鬼哥说故事 闲话少说,so的改动,重要性大家都知道,这里从头编写so文件,分析so文件,改动so文件,打算做一个系列的教程,当然,主要是看时间同意. android的sdk配置以及ndk环境 ...
- 操作引入xml文件的书包(定位到指定节点)
定位到指定节点:e0.1 <chtml><we>@{_samples/test.xml:HtokID=e0.1}</we></chtml> 上述表达式表 ...
- xhr的send方法以及node如何处理get和post数据
起因:看了阮一峰老师的关于上传文件的文章,进行测试,在使用xhr对象的send方法时遇到问题. 遇到的问题是使用send方法传送过去的数据,在node后台无法接收,经过很多次测试,怀疑是不是send与 ...