一、模板

算法解析: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. UNITY自带的PACKAGE的UTILITY 里面有一个自带的FPS COUNTER

    UNITY自带的PACKAGE的UTILITY 里面有一个自带的FPS COUNTER 可用,但是脚本是保密的?

  2. [LeetCode] Reorder List 链表重排序

    Given a singly linked list L: L0→L1→…→Ln-1→Ln, reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You must do th ...

  3. [LeetCode] Edit Distance 编辑距离

    Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2 ...

  4. 浅谈 Web 中前后端模板引擎的使用

    前言 这篇文章本来不打算写的,实话说楼主对前端模板的认识还处在非常初级的阶段,但是为了整个 源码解读系列 的完整性,在深入 Underscore _.template 方法源码后,觉得还是有必要记下此 ...

  5. modelsim实用教程--前言

    前言 Modelsim是一款专业的仿真软件,特别是在Quartus II 11.0之后的版本,都没有配套自身的仿真软件,所以Modelsim成了在FPGA设计流程中的进行功能仿真的首选仿真软件之一. ...

  6. @RenderSection,@RenderPage,@RenderBody介绍

    在MVC的模板页中会用到上面三个东西,那么今天就简单归纳下各有什么作用 1.@RenderSection 用法 对CSS或JS部分模块的预留定义 例如模板页定义了@RenderSection(&quo ...

  7. Alpha阶段总结

    Alpha阶段的验收已经完成,8个小组都展现了他们经过连夜奋战后的成果.相比过往几届,这是第一次8个小组全部顺利演示操作完成,没有个别小组因为任务未完成而延宕演示的情况发生.Alpha演示,各组都实现 ...

  8. vue.js 第五课

    计算属性 1.基础例子 2.计算属性 vs $watch 3.计算 setter 4.计算属性开发实务demo   1.计算属性 computed( 电脑computer) (区别普通属性) 计算属性 ...

  9. 关于iOS特定设别推送(特定用户推送)【原】

    在这里,我就不哆嗦如何制作推送证书之类的了,网上一搜一大堆. 我们现在很多开发者的推送,就是集成第三方的推送SDK,然后通过第三方的推送平台帮我们进行推送.其实,这种推送(如JPush),一般只能广播 ...

  10. jQuery种种

    jquery UI autocomplete获得焦点自动弹出跟随下拉框--http://blog.csdn.net/jiusong_mi/article/details/49249853 $(&quo ...