manacher算法用来求解回文串问题,时间复杂度为O(n).

不懂的先可以去练习下模板板子题,求最长回文串

传送门P3501 [POI2010]ANT-Antisymmetry
这一题他给的是一个新的定义“反对称”字符串:
如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串。比如00001111和010101就是反对称的,1001就不是。
我们可以了利用0/1的性质,由于0/1始终不能与自己相反,故子串并不存在中央位置,我们只能从自己添加的特殊符号’#'的奇数位上找
,差不多就是manacher的一个模板题,就是循环时的判定条件发生了变化,回文串求的是str[i - Len[i]]== str[i + Len[i]],这里我们可以直接check来判定

bool check(char i, char j) {if(((i - '0') ^ (j - '0')) == 1) return 1;//如果俩个数相反if(i == '#' && j == '#') return 1;//如果特殊符号相等返回1return 0;
}

不知名的代码

#include<bits/stdc++.h>
using namespace std;
const int N=2000010;
int p[N],n,m;
char s[N],str[N];
int len;bool check(char i, char j) {if(((i - '0') ^ (j - '0')) == 1) return 1;//如果俩个数相反if(i == '#' && j == '#') return 1;//如果特殊符号相等返回1return 0;
}
void manacher()
{p[0]=0;int mx=0;int id=0;int k=0;str[k++]='%';str[k++]='#';for(int i=0;i<n;i++){str[k++]=s[i];str[k++]='#';}len=k;for(int i=1;i<len;i+=2)//数字只会出现在偶数上,我们只要枚举所有的奇数位'#'来作为分割线{if(i<mx) p[i]=min(mx-i,p[2*id-i]);else p[i]=1;while(check(str[i-p[i]],str[i+p[i]])) p[i]++;//改变判定条件if(p[i]+i>mx){mx=p[i]+i;id=i;}}long long  ans=0;// cout<<len<<endl;// for(int i=1;i<=len-1;i++)// cout<<str[i]<<" ";// cout<<endl;for(int i=1;i<=len-1;i+=2){// cout<<p[i]<<"   ";if(p[i]>1) ans+=p[i]/2;}//  if(p[i]>1) ans+=p[i]/2;cout<<ans<<endl;}int main()
{scanf("%d",&n);scanf("%s",s);manacher();return 0;
}

不知道为什么p[i]/2的可以自己枚举一下

P4555 [国家集训队]最长双回文串

这一题又是一个整活题目,他要求的是最长双回文串
想到回文串我们就能利用manacher算法
该题目的双回文串就是:把一个字符串baacaabbacabb拆开
可以拆开为aacaa,bbacabb两个回文子串,求这个两个回文子串的最大长度是多少

我们可以利用’#'来当作切割的位置,求这个位置作为回文串的左端点的最大长度和作为右端点的最大长度,然后枚举一边加起来即可。
中间转移时我们可以利用dp

  for(int i=1 ;i<=len-1 ;i+=2) {L[i] = max(L[i] , L[i-2] -2 );}

这里转移是我们找最大长度,L[i-2]是我们只找’#‘上的位置,
L[i-2]-2是该位置L[i]在上一个位置的后面两位,回文串的长度也要 -2
转移过程

不知名代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int Len[N],r[N];
int len;
int R[N],L[N];
char s[N],str[N];
int n,m;void manacher()
{// memset(str,0,sizeof(str));len=strlen(s);int k=0;str[k++] = '$';for(int i=0;i<len;i++){str[k++]='#';str[k++]=s[i];}str[k++]='#';len=k;Len[0]=0;int mx=0;int id=0;for(int i=1 ;i<len ;i++){if( i < mx ) Len[i] = min(Len[2*id-i] , mx-i);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;}int r = i+Len[i]-1;int l = i-Len[i]+1;// printf("%d %d %d %d\n",i,r,l,Len[i]-1);L[l] = max(Len[i]-1,L[l]);//以l为回文串的左端点的最长回文串R[r] = max(Len[i]-1,R[r]);//以r为回文串的右端点的最长回文串}
}int main()
{scanf("%s",s);manacher();int ans=0;for(int i=1 ;i<=len-1 ;i+=2) {L[i] = max(L[i] , L[i-2] -2 );}//for(int i=1;i<=len;i+=2)//cout<<L[i]<<" ";for(int i=len-1 ;i>=1 ;i-=2) R[i] = max(R[i] , R[i+2] - 2 );for(int i=1 ;i<=len-1;i+=2){if(R[i]&&L[i])ans = max(ans , L[i] + R[i]);}cout<<ans<<endl;return 0;
}

P1659 [国家集训队]拉拉队排练

这题求的是前K大的回文串长度的乘积,也相当于一个板子题。
这题有个巨恶心的地方,最后一个点数据很大,要用快速幂qmi
来写,然后这题只要我们求回文串长度为奇数的回文串,最后枚举所有回文串长度时偶数直接可以跳过

不知名的代码

#include<bits/stdc++.h>
using namespace std;
const int N=3000010,mod=19930726;
typedef long long ll;
int Len[N];
char s[N],str[N];
ll cnt[N],sum,id,len;
ll n,m,K;void manacher()
{int k=0;str[k++]='%';for(int i=0;i<n;i++){str[k++]='#';str[k++]=s[i];}str[k++]='#';len=k;// cout<<len<<endl;Len[0]=0;int mx=0;for(int i=1;i<len;i++){if(i<mx) Len[i]=min(mx-i,Len[2*id-i]);else Len[i]=1;while(str[Len[i]+i]==str[i-Len[i]]) Len[i]++;if(Len[i]+i>mx){mx=Len[i]+i;id=i;}if((Len[i]-1)%2) cnt[Len[i]-1]++;}// cout<<sum-1<<endl;
}ll qmi(int x,int y)
{if(x==1) return 1;ll base=x,res=1;while(y){if(y&1) res=(res*base)%mod;base=(base*base)%mod;y>>=1;}return res;
}void solve()
{ll ans=1;sum=0;for(int i=n;i>=1;i--){if(i%2==0) continue; // printf("%d %d\n",i,cnt[i]);sum+=cnt[i];if(K>=sum){ans*=qmi(i,sum)%mod;K-=sum;}else {ans*=qmi(i,K)%mod;K-=sum;break;}// cout<<ans<<endl;}if(K>0) cout<<-1<<endl;else printf("%lld\n",ans);}int main()
{scanf("%d%lld",&n,&K);scanf("%s",s);manacher();solve();return 0;
}

(manacher)马拉车算法专题题目相关推荐

  1. 【算法】Manacher(马拉车)算法

    原jekyll 2019-09-07 Manacher's Alogrithm,中文名叫马拉车算法,是一位叫Manacher的人在1975年提出的一种算法,解决的问题是求最长回文子串,算法的神奇之处就 ...

  2. Manacher马拉车算法求最长回文子串

    终于把马拉车算法搞明白了!赶紧记录一下. 这个算法用于查找一个字符串的最长回文子串 马拉车算法依次给数组p[i]赋值,马拉车算法的本质就是在每次给数组p[i] 赋值时尝试进行偷懒 例如,当要给p[6] ...

  3. Manacher(马拉车)算法—简略讲解

    这是一篇菜鸡的算法小笔记!希望你喜欢! 前言 马拉车算法是用来查找一个字符串的最长回文子串的线性方法,是一个叫 Manacher 的人在 1975 年发明的,这个方法的最大贡献是在于将时间复杂度提升到 ...

  4. Manacher (马拉车)算法

    Manacher于1975年发现了一种线性时间算法,可以在列出给定字符串中从任意位置开 始的所有回文子串.同样的算法也可以在任意位置查找全部极大回文子串,并且时间复杂 度是线性的.那他是怎样实现的呢, ...

  5. manacher马拉车算法

    算法讲解 算法讲解1 #include <iostream> #define maxn 10e+6; using namespace std; char s[maxn],str[maxn* ...

  6. Manacher(马拉车算法)

    对应letecode链接: https://leetcode-cn.com/problems/longest-palindromic-substring/ 题目描述: 给你一个字符串 s,找到 s 中 ...

  7. 什么是Manacher(马拉车)算法-java代码实现

    截止到目前我已经写了 500多道算法题,其中部分已经整理成了pdf文档,目前总共有1000多页(并且还会不断的增加),大家可以免费下载 下载链接:https://pan.baidu.com/s/1hj ...

  8. 最长回文 HDU - 3068(求最长回文串的长度【马拉车算法Manacher】)

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

  9. 最长回文串 马拉车算法 C++

    最长回文串 LeetCode 5.最长回文串 给你一个字符串 s,找到 s 中最长的回文子串. 示例 1: 输入:s = "babad" 输出:"bab" 解释 ...

最新文章

  1. 数据科学工作者(Data Scientist) 的日常工作内容包括什么?
  2. Jetty 基本使用样例
  3. UA MATH566 统计理论4 贝叶斯统计基础1
  4. linux递归赋权限,Linux下递归更改文件夹和子文件夹的权限
  5. linux的mysql服务器密码忘了,怎么解决?
  6. 1.CCProgressTo进度动作,条形进度条,扇形进度条
  7. LiveVideoStack线上交流分享 ( 八 ) —— TCP的困境与解决方案
  8. 关于web工程项目路径的一些说明
  9. “嘲羊群众”词条视频惹怒粉丝 百度知道向张艺兴道歉...
  10. 周志华团队和蚂蚁金服合作:用分布式深度森林算法检测套现欺诈
  11. Less颜色混合函数(14)
  12. 图片裁剪,合成(设置透明背景)
  13. TrueNAS静态IP设置
  14. kettle日志解析_Kettle运行日志记录
  15. 马云卸任演讲全文:青山不改 绿水长流 后会有期
  16. 【参会指南】PPP全球数字资产投资峰会之金融科技区块链支持可持续发展
  17. windows蓝牙编程—— 0 获取本地蓝牙的句柄和信息
  18. ​STM32家族介绍,覆盖STM32F、STM32H、STM32L全系列
  19. php数据group去重,MongoDB_Mongodb聚合函数count、distinct、group如何实现数据聚合操作, 上篇文章给大家介绍了Mong - phpStudy...
  20. vi格式化输出Json格式数据方便查看修改

热门文章

  1. HUSTOJ特判程序Special Judge使用方法整理
  2. 2017中国(上海)国际物联网大会在沪举办
  3. WMS仓储管理系统解决方案能帮助电子企业解决哪些问题
  4. 【Adams-Car】专栏目录汇总
  5. 展锐camera 调用流程
  6. 永磁同步电机控制系统——模型预测控制(MPC)
  7. 计算机网络知识全面讲解:域名的结构
  8. Android开发之SoundPool详解
  9. Park变换输入输出前后都是交流量的问题及解决办法
  10. [Android 基础] -- Android 属性系统简介