目的:线性查找一个串的最长回文子串

时间复杂度:O(n)

len[i]表示以i为中心的回文串的半径,mx即为当前计算回文串最右边字符的最大值,p是中心点mid,mx-i和2*p-1关于p对称

https://blog.csdn.net/csdn_kou/article/details/82917937

hdu3068,板子题,求最长回文长度。

#include<bits/stdc++.h>
using namespace std;
const int maxn=;
int t,len[maxn*];
char S[maxn*],T[maxn*],s[maxn*]; int init(char *str)
{
int n=strlen(str);
for(int i=,j=;i<=*n;j++,i+=)
{
s[i]='#';
s[i+]=str[j];
}
s[]='$';
s[*n+]='#';
s[*n+]='@';
s[*n+]='\n';
return *n+;
}
void manacher(int n)
{
int mx=,p=;
for(int i=;i<=n;i++)
{
if(mx>i)len[i]=min(mx-i,len[*p-i]);
else len[i]=;
while(s[i-len[i]]==s[i+len[i]])len[i]++;
if(len[i]+i>mx)mx=len[i]+i,p=i;
}
} int main()
{
while(scanf("%s",S)!=EOF)
{
int Len=strlen(S),n=init(S);
for(int i=;i<=n;i++)len[i]=;
manacher(n); int ans=;
for(int i=;i<=n;i++)
{
ans=max(ans,len[i]-);
}
printf("%d\n",ans);
}
return ;
}

2019徐州G colorful string,求所有回文子串的value之和,一个串的value为串中字母种类,dfs预处理了第i位前一个a-z的位置,复杂度26*n。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+;
int t,len[maxn*];
char S[maxn*],T[maxn*],s[maxn*]; int init(char *str){
int n=strlen(str);
for(int i=,j=;i<=*n;j++,i+=){
s[i]='#';
s[i+]=str[j];
}
s[]='$';
s[*n+]='#';
s[*n+]='@';
s[*n+]='\n';
return *n+;
} void manacher(int n)
{
int mx=,p=;
for(int i=;i<=n;i++){
if(mx>i) len[i]=min(mx-i,len[*p-i]);
else len[i]=;
while(s[i-len[i]]==s[i+len[i]]) len[i]++;
if(len[i]+i>mx) mx=len[i]+i,p=i;
}
} int dp[maxn*][],place[];
int main()
{
scanf("%s",S);
int Len=strlen(S),n=init(S);
for(int i=;i<=n;i++)len[i]=;
manacher(n); ll ans=;
int k=;
for(int i=;i<;i++)place[i]=-;
for(int i=;i<=n;i++)
{
if(i%==)place[S[k++]-'a']=i;
for(int j=;j<;j++)dp[i][j]=place[j];
} for(int i=;i<=n;i++)
{
for(int j=;j<;j++)
{
if(i-dp[i][j]<len[i])
{
ans+=1ll*(len[i]-(i-dp[i][j]))/;
}
}
}
printf("%lld\n",ans); return ;
}

hdu3613,一个串割成两个串,如果是回文串则val为所有字母val之和,否则为零。

字母的val题目给出,求使总串的val最高的割法的val值。

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+;
int t,len[maxn<<];
char S[maxn<<],T[maxn<<],s[maxn<<]; int init(char *str)
{
int n=strlen(str);
for(int i=,j=;i<=*n;j++,i+=)
{
s[i]='#';
s[i+]=str[j];
}
s[]='$';
s[*n+]='#';
s[*n+]='@';
s[*n+]='\n';
return *n+;
}
void manacher(int n)
{
int mx=,p=;
for(int i=;i<=n;i++)
{
if(mx>i)len[i]=min(mx-i,len[*p-i]);
else len[i]=;
while(s[i-len[i]]==s[i+len[i]])len[i]++;
if(len[i]+i>mx)mx=len[i]+i,p=i;
}
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int val[]={};
for(int i=;i<;i++)scanf("%d",&val[i]);
cin>>S;
int Len=strlen(S),n=init(S);
for(int i=;i<=n;i++)len[i]=;
manacher(n); int lg=,rg=,ans=;
for(int i=;i<Len;i++)rg+=val[S[i]-'a'];
for(int i=;i<=n;i++)
{
if(i%==)
{
lg+=val[s[i]-'a'];
rg-=val[s[i]-'a'];
}
else
{
int l=,r=*Len+,tmplg=,tmprg=;
if(i!=l&&i!=r)
{
int mid1=(l+i)>>,mid2=(i+r)>>;
if(len[mid1]==mid1-l+)tmplg=lg;
if(len[mid2]==r-mid2+)tmprg=rg;
ans=max(ans,tmplg+tmprg);
}
}
}
printf("%d\n",ans);
}
return ;
}

hdu3294,求最早出现的最长回文串的l、r区间,并且转换后输出

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+;
int t,len[maxn<<];
char S[maxn<<],T[maxn<<],s[maxn<<];
int init(char *str)
{
int n=strlen(str);
for(int i=,j=;i<=*n;j++,i+=)
{
s[i]='#';
s[i+]=str[j];
}
s[]='$';
s[*n+]='#';
s[*n+]='@';
s[*n+]='\n';
return *n+;
}
void manacher(int n)
{
int mx=,p=;
for(int i=;i<=n;i++)
{
if(mx>i)len[i]=min(mx-i,len[*p-i]);
else len[i]=;
while(s[i-len[i]]==s[i+len[i]])len[i]++;
if(len[i]+i>mx)mx=len[i]+i,p=i;
}
} int main()
{
char ch;
while(scanf("%c %s",&ch,S)!=EOF)
{
int Len=strlen(S),n=init(S);
for(int i=;i<=n;i++)len[i]=;
manacher(n); int ans=,l=,r=;
for(int i=;i<=n;i++)
{
if(len[i]->ans)
{
ans=len[i]-;
l=(i-len[i]+)/;
r=(i+len[i]-)/;
}
}
if(ans<)printf("No solution!\n");
else
{
printf("%d %d\n",l,r);
for(int i=l;i<=r;i++)
{
S[i]=S[i]-ch+'a';
if(S[i]>'z')S[i]=S[i]-'z'+'a'-;
if(S[i]<'a')S[i]=S[i]+'z'-'a'+;
}
S[r+]='\0';
printf("%s\n",S+l);
}
getchar();
}
return ;
}

hdu4513,最长递增(不降)回文串,manacher里只需要改个while

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+;
int t,len[maxn*];
int s[maxn*],T[maxn*],S[maxn*]; int init(int *str,int n)
{
for(int i=,j=;i<=*n;j++,i+=)
{
s[i]=-;
s[i+]=str[j];
}
s[]=-;
s[*n+]=-;
s[*n+]=-;
return *n+;
}
void manacher(int n)
{
int mx=,p=;
for(int i=;i<=n;i++)
{
if(mx>i)len[i]=min(mx-i,len[*p-i]);
else len[i]=;
while(s[i-len[i]]==s[i+len[i]]&&s[i-len[i]]<=s[i-len[i]+])len[i]++;
if(len[i]+i>mx)mx=len[i]+i,p=i;
}
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=;i<n;i++)
scanf("%d",&S[i]);
int Len=n,len2=init(S,n);
for(int i=;i<=n;i++)len[i]=;
manacher(len2); int ans=;
for(int i=;i<=len2;i++)
{
ans=max(ans,len[i]-);
}
printf("%d\n",ans);
}
return ;
}

...

马拉车manacher的更多相关文章

  1. 51nod 1595 回文度 | 马拉车Manacher DP

    51nod 1595 回文度 题目描述 如果长度为n的字符串是一个回文串,同时它的长度为floor(n/2)的前缀和后缀是K-1度回文串,则这个字符串被称为K度回文串.根据定义,任何字符串(即使是空字 ...

  2. HDU - 3068 最长回文(马拉车Manacher)题解

    思路:马拉车裸题,我们用一个p[i]数组代表以i为中心的最大回文半径.这里用了一个小技巧,如果一个串是aaaa这样的,那我们插入不相干的字符使它成为#a#a#a#a#,这样无论这个串是奇数还是偶数都会 ...

  3. hdu3068-最长回文-马拉车(Manacher)算法

    http://acm.hdu.edu.cn/showproblem.php?pid=3068 脑子转个弯总算看懂马拉车算法了.记录一下思路和模板. 马拉车算法是在O(n)的时间内求出最大回文子串. 一 ...

  4. 马拉车——Manacher一篇看上去很靠谱的理解(代码显然易懂)

    由于回文分为偶回文(比如 bccb)和奇回文(比如 bcacb),而在处理奇偶问题上会比较繁琐,所以这里我们使用一个技巧,在字符间插入一个字符(前提这个字符未出现在串里).举个例子:s="a ...

  5. 一点总结-关于debug比赛

    上午的题目是: 1. main里面定义的变量必须手动初始化,使用memset或者其他,函数外或者函数内,会进行初始化为0. 2. 最长回文子串的马拉车manacher算法,不会写! 3. 数字三角形d ...

  6. ACM-ICPC 2018 南京网络赛

    题目顺序:A C E G I J L A. An Olympian Math Problem 打表,找规律,发现答案为n-1 C. GDY 题意: m张卡片,标号1-13: n个玩家,标号1-n:每个 ...

  7. ACM模板_axiomofchoice

    目录 语法 c++ java 动态规划 多重背包 最长不下降子序列 计算几何 向量(结构体) 平面集合基本操作 二维凸包 旋转卡壳 最大空矩形 | 扫描法 平面最近点对 | 分治 最小圆覆盖 | 随机 ...

  8. [菜b]Isaunoya 的一些学习笔记…[保持咕咕咕]

    fread/fwrite标记永久化 分块 树链剖分 莫比乌斯反演 斜率优化/单调队列 kruskal重构树 回滚莫队 可持久化线段树/trie树 Link-Cut-Tree dsu on tree F ...

  9. Manacher's Algorithm 马拉车算法

    这个马拉车算法Manacher‘s Algorithm是用来查找一个字符串的最长回文子串的线性方法,由一个叫Manacher的人在1975年发明的,这个方法的最大贡献是在于将时间复杂度提升到了线性,这 ...

随机推荐

  1. windows中修改IP映射的位置

    windows中修改IP映射的位置 置顶 2018年08月05日 14:42:44 wangxiaolong0 阅读数:1473   在安装linux之后,发现windows不能通过映射来访问linu ...

  2. Spring Boot2 系列教程(二十六)Spring Boot 整合 Redis

    在 Redis 出现之前,我们的缓存框架各种各样,有了 Redis ,缓存方案基本上都统一了,关于 Redis,松哥之前有一个系列教程,尚不了解 Redis 的小伙伴可以参考这个教程: Redis 教 ...

  3. HTML的条件注释和hack技术

    在很多时候,前端的兼容性问题,都很让人头痛!幸运的是,微软从去年声明:从2016年1月12日起,微软将停止为IE8(包括IE8)提供技术支持和安全更新.整个前端圈子都沸腾起来,和今年七月份Adobe宣 ...

  4. vim-plug 安装 jedi-vim

    安装: Plug 'davidhalter/jedi-vim' :PlugInstall 我就在配置文件里写了一个配置项 let g:jedi#use_tabs_not_buffers = 1 进入定 ...

  5. 【Oracle】Oracle ASM管理监控命令

    目录 Oracle ASM管理监控命令 目的: 1.查看磁盘组 2.查看目前归档 3.查看ASM的磁盘路径 4. asmcmd Oracle ASM管理监控命令 目的: 查看目前Oracle ASM相 ...

  6. Redis 4.0鲜为人知的功能将加速您的应用程序

    来源:Redislabs 作者:Kyle Davis 翻译:Kevin (公众号:中间件小哥) Redis 4.0给Redis生态带来了一个惊人的功能:Modules(模块).Modules是Redi ...

  7. 京东物流出问题了?褥了30块羊毛 & 浅析系统架构

    本人亲身经历,但后续的流程分析都是个人猜测的,毕竟没有实际做过这块的业务. 订单物流阻塞经过 火热的双11刚刚退去,截止今日,我在京东购买的矿泉水终于到货啦,下单两箱还只收到了一箱 :( ,从下单到收 ...

  8. /etc/security/limits.conf配置文件详解

    这个文件主要是用来限制用户对系统资源的使用.是/lib64/security/pam_limits.so模块对应的/etc/serurity/pam_limits的配置文件. # /etc/secur ...

  9. 《手把手教你》系列练习篇之4-python+ selenium自动化测试(详细教程)

    1.  简介 今天我们继续前边的练习,学习和练习一下:如何使用webdriver方法获取当前测试页面的URL.如何获取当前页面的title. 2. webdriver方法获取当前测试页面的URL 本小 ...

  10. Flink中的CEP复杂事件处理 (源码分析)

    其实CEP复杂事件处理,简单来说你可以用通过类似正则表达式的方式去表示你的逻辑,表现能力非常的强,用过的人都知道 开篇先偷一张图,整体了解Flink中的CEP中的  一种重要的图  NFA非确定有限状 ...