一、模板

算法解析:http://www.felix021.com/blog/read.php?2040

 *主要用来解决一个字符串中最长回文串的长度,在O(n)时间内,线性复杂度下,求出以每个字符串为中心的最长回文,奇数回文跟偶数回文一起考虑了
S $ # # # # # # # # #
P 最后所求的值就是max(P[i]-) //输入,并处理得到字符串s,s[0]=$
void getp()
{
int p[], mx = , id = ;
memset(p, , sizeof(p));
for (i = ; s[i] != '\0'; i++)
{
p[i] = mx>i ? min(p[*id-i], mx-i) : ;
while (s[i + p[i]] == s[i - p[i]]) p[i]++;
if (i + p[i] > mx)
{
mx = i + p[i];
id = i;
}
}
}

二、题目

1、【HDU 4513】吉哥系列故事――完美队形II

题意:输入n(1 <= n <= 100000)个人的身高hi(50 <= hi <= 250),从这些人中连续挑出k个人,这k个人【身高是左右对称的,如果是k是奇数,那么中间那个人的身高任意】&&【从左到中间那个人,身高需保证不下降,如果用H表示新队形的高度,则H[1] <= H[2] <= H[3] .... <= H[mid]】,求k的最大值。

解题思路:一般的manacher添加的是’#’,但是本题左半边的身高不递减,所以添加的应该是(h[i]+h[i+1])/2,注意细节。处理后的第奇数个身高是添加上去的,第偶数个身高是一开始输入的,当i-p[i]是奇数时,无论hh[i-p[i]]与hh[i+p[i]]是否相等,p[i]都应该+1。

比如:h[] = 80 60 70 60 90 50 ==> hh[] = -1 65  70  65  65  75  70  65【有颜色的是原串】,以70为中心时,p[6]=4而不是3

 #include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int N=*1e5+;
int h[N], hh[N];
int t, n;
int p[N], lenhh;
void getp()
{
int mx = , id = ;
memset(p, , sizeof(p));
for (int i = ; i<lenhh; i++)
{
p[i] = mx>i ? min(p[*id-i], mx-i) : ;
while(hh[i + p[i]] == hh[i - p[i]] && hh[i-p[i]]<=hh[i-p[i]+]) p[i]++;
if((i-p[i])%) p[i]++;
if (i + p[i] > mx)
{
mx = i + p[i];
id = i;
}
}
}
int main(){
scanf("%d", &t);
while(t--){
scanf("%d", &n);
for(int i=; i<=n; i++){
scanf("%d", &h[i]);
}
h[]=h[n], h[n+]=h[];
lenhh=;
hh[]=(h[]+h[])/, hh[]=-;
for(int i=; i<=n; i++){
hh[lenhh++]=h[i];
hh[lenhh++]=(h[i]+h[i+])/;
}
// for(int i=0; i<lenhh; i++) cout<<hh[i]<<" ";
// cout<<endl;
getp();
int maxn=;
// for(int i=0; i<lenhh; i++) cout<<p[i]<<" ";
// cout<<endl;
for(int i=; i<lenhh; i++) maxn = max(maxn, p[i]-);
printf("%d\n", maxn);
}
return ;
}

2、【HDU 3948】The Number of Palindromes(manacher +建图 || )

题意:输入一个字符串(len<=1e5),求这个字符串中不同的回文子串的个数,如:【输入aaaa,有四个不同的回文子串,a、aa、aaa、aaaa】

解题思路:先用计算字符串的hash值,manacher算法求出p[],枚举每一个中心点,从可能的最长回文串的两端逐渐向里判断是否出现过,如果长的出现过了,那短的也一定出现过。判断这个字符串是否出现过目前一共有两种方法:【最后的点的总数不会超过3*1e5的,那就将每一个hash值都对mod(mod=3*1e5+10)取余,建图,hash值%mod后相等的利用head连成一个图】&&【这一种方式就是比较费时但也比较直接的,直接用map判断这个hash值是不是出现过】

Get新技能:将判断字符串是否出现过转化为判断hash值是不是出现过,同时建图判断hash值是否出现过。

manacher+建图

 #include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
using namespace std; #define ull unsigned long long
#define ll __int64 const int N = 1e5+;
const ull bas = ;
ull has[N], base[N];
char s[N], ss[*N];
int lenss, p[*N]; struct hash_map{
const static int mod=*N+;//一个静态的、值不能被改变的整型常量
int idx, head[mod]; struct hash_tables{
int next;
ull key;
}ele[*N]; void init(){
idx = ;
memset(head, 0xff, sizeof(head));//初始化为-1
} void clear(){// clear的效率要高于init的效率,后期的用以替换init
for(int i=; i<idx; i++){
head[ele[i].key%mod] = -;
}
idx = ;
} void insert(ull x){
int tmp = x%mod;
ele[idx].key = x;
ele[idx].next = head[tmp];
head[tmp] = idx++;
} bool find(ull x){
int hashcode = x%mod;
for(int i=head[hashcode]; i!=-; i=ele[i].next){
if(ele[i].key == x) return true;
}
return false;
}
}hashi; // 将hash表的实现封装成一个类 ll ans; void manacher(){
int mx = , id = ;
memset(p, , sizeof(p));
for (int i = ; i<lenss; i++)
{
p[i] = mx>i ? min(p[*id-i], mx-i) : ;
while (ss[i + p[i]] == ss[i - p[i]]) p[i]++;
if (i + p[i] > mx)
{
mx = i + p[i];
id = i;
}
}
}
void init(){
ss[] = '$', ss[] = '#';
lenss = , has[]=;
int len=strlen(s);
for(int i=; i<len; i++){
has[i+] = has[i]*bas+s[i]-'a'+;
ss[lenss++] = s[i];
ss[lenss++] = '#';
}
ss[lenss]='\0';
manacher();
}
int begn, ed;
void find(int id, int dis){
begn=id-dis+, ed=id+dis-;
if(begn%==) begn++, ed--;
while(begn<=ed){
ull k = has[ed/] - has[begn/-]*base[ed/-begn/+];
if(!hashi.find(k)){
hashi.insert(k);
ans++;
}
else break;
begn+=, ed-=;
}
}
int main(){
int t, cas=;
scanf("%d", &t);
hashi.init();
base[] = ;
for(int i=; i<N; i++) base[i] = base[i-]*bas; while(t--){
hashi.clear();
scanf("%s", s);
init(); ans = ;
for(int i=; i<lenss; i++){
find(i, p[i]);
}
printf("Case #%d: %I64d\n", cas++, ans);
}
return ;
}

manacher+map

 #include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
using namespace std; #define ull unsigned long long const int N = 1e5+;
const ull bas = ;
ull has[N], base[N];
char s[N], ss[*N];
int lenss, p[*N];
map<ull, int>mp; int ans; void manacher(){
int mx = , id = ;
memset(p, , sizeof(p));
for (int i = ; ss[i] != '\0'; i++)
{
p[i] = mx>i ? min(p[*id-i], mx-i) : ;
while (ss[i + p[i]] == ss[i - p[i]]) p[i]++;
if (i + p[i] > mx)
{
mx = i + p[i];
id = i;
}
}
}
void init(){
ss[] = '$', ss[] = '#';
lenss = , has[]=;
int len = strlen(s);
for(int i=; i<len; i++){
has[i+] = has[i]*bas+s[i]-'a'+;
ss[lenss++] = s[i];
ss[lenss++] = '#';
}
ss[lenss] = '\0';
manacher();
}
int begn, ed;
void find(int id, int dis){
begn=id-dis+, ed=id+dis-;
if(begn%==) begn++, ed--;
while(begn<=ed){
ull k = has[ed/] - has[begn/-]*base[ed/-begn/+];
if(!mp[k]){
mp[k] = ;
ans++;
}
else break;
begn+=, ed-=;
}
}
int main(){
int t, cas=;
scanf("%d", &t); base[] = ;
for(int i=; i<N; i++) base[i] = base[i-]*bas; while(t--){
scanf("%s", s);
init(); ans = , mp.clear();
for(int i=; i<lenss; i++){
find(i, p[i]);
}
printf("Case #%d: %d\n", cas++, ans);
}
return ;
}

manacher算法专题的更多相关文章

  1. HDU3068 回文串 Manacher算法

    好久没有刷题了,虽然参加过ACM,但是始终没有融会贯通,没有学个彻底.我干啥都是半吊子,一瓶子不满半瓶子晃荡. 就连简单的Manacher算法我也没有刷过,常常为岁月蹉跎而感到后悔. 问题描述 给定一 ...

  2. lintcode最长回文子串(Manacher算法)

    题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ 最长回文子串 给出一个字符串 ...

  3. 1089 最长回文子串 V2(Manacher算法)

    1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 回文串是指aba.abba.cccbccc.aaaa ...

  4. 51nod1089(最长回文子串之manacher算法)

    题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1089 题意:中文题诶~ 思路: 我前面做的那道回文子串的题 ...

  5. LeetCode 5 Longest Palindromic Substring manacher算法,最长回文子序列,string.substr(start,len) 难度:2

    https://leetcode.com/problems/longest-palindromic-substring/ manacher算法相关:http://blog.csdn.net/ywhor ...

  6. 求最长回文子串:Manacher算法

    主要学习自:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html 问题描述:回文字符串就是左右 ...

  7. 【转】最长回文子串的O(n)的Manacher算法

    Manacher算法 首先:大家都知道什么叫回文串吧,这个算法要解决的就是一个字符串中最长的回文子串有多长.这个算法可以在O(n)的时间复杂度内既线性时间复杂度的情况下,求出以每个字符为中心的最长回文 ...

  8. Manacher算法

    Manacher算法是求回文串最高效的算法,能在线性时间内求出以每一个字符为中心的最长回文串.   首先,我们都能想出$O(N^2)$求出每一个字符为中心的最长回文串的算法.那么我们考虑这样一种情况. ...

  9. 字符串匹配--manacher算法模板

    manacher算法主要是处理字符串中关于回文串的问题的,它可以在 O(n) 的时间处理出以字符串中每一个字符为中心的回文串半径,由于将原字符串处理成两倍长度的新串,在每两个字符之间加入一个特定的特殊 ...

随机推荐

  1. TortoiseSvn的安装过程详解

    运行TortoiseSVN-1.6.6.17493-win32-svn-1.6.6.msi程序, 开始安装 点击Next, 下一步 选择 I accept 接受, 点击Next, 下一步 选择安装路径 ...

  2. AC日记——楼房 codevs 2995

    2995 楼房  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description 地平线(x轴)上有n个矩(lou ...

  3. 利用线上数据验证系统 Gor

    Web 应用性能和压力测试工具 Gor - 运维生存时间 http://hao.jobbole.com/gorhttp/ 要使用线上引流到测试环境的作用,需要做到以下几点: 1.新搭建一套测试环境,连 ...

  4. node基础12:动态网页

    1.显示动态网页 又到了激动人心的时刻,马上就可以使用node创建动态网站了,其原理为: 在HTML模板中使用占位符 根据请求路径,确定需要返回的页面 根据请求参数来确定静态模板中占位符的值 使用正则 ...

  5. common-pool2 学习:thrift连接池的另一种实现

    对象池是一种很实用的技术,经典的例子就是数据库连接池.去年曾经从零开始写过一个thrift客户端连接池.如果不想重造轮子,可以直接在apache开源项目commons-pool的基础上开发. 步骤: ...

  6. FineUI(专业版)v3.2.0 发布(ASP.NET UI控件库)!

    +2016-08-20 v3.2.0 +表格增强. +表格列RenderField增加属性ClientHtmlEncode,用于在客户端进行HTML编码. -增加示例:单元格编辑->杂项-> ...

  7. 网站收集ing....

    1.账号注册网址 http://bugmenot.com/ PS:只要输入相关网站域名就能立即完成网站注册 2.博客网站 CSDN,博客园,开源中国 3.破解网站 吾爱破解 4.矢量图标 http:/ ...

  8. C++知识回顾(二)——名称空间

    随着工程的增大,名称相互冲突的肯能性增加,使用多个厂商的类库时,可能导致名称冲突.为了解决这些问题,需要用到名称空间. 为了将代码加入名称空间,可以使用namespae将其包含,例如,编写一段代码,其 ...

  9. js或css文件后面的参数是什么意思?

    经常看到不少导航网站测样式或js文件后面加了一些参数,主要是一你为一些并不经常更新的页面重新加载新修改的文件. 经常遇到页面里加载的js与css文件带有参数,比如: <script type=& ...

  10. windows多线程编程

    进程共同实现某个任务或者共享计算机资源, 它们之间存在两种关系: 1.同步关系, 指为了完成任务的进程之间, 因为需要在某些位置协调它们的执行顺序而等待, 传递消息产生的制约关系. 2.互斥关系, 进 ...