带上 POJ 3974 Palindrome , 谈谈我对Manacher算法的理解(注释版代码)

原题:http://fastvj.rainng.com/problem/21720/origin

题意: Manacher模板题

在B站有人上传了Kuangbin的直播录像,正好有讲Manacher算法的,在这里安利一下

------我对Manacher的理解:

首先定义两个数列,ma和mp

ma数组(manacher的简称):用于存储修改后的字符串。 为什么需要修改呢,原因是字符串有奇有偶处理起来不方便,于是可以统一将其变成奇数,做法就是在每一个字符前后都加入一个该字符串从来没有出现过的字符,根据惯例,选用‘#’,然后在最开头加上另外一个没出现过的字符,作为边界判断,同样惯例采用’$’,至于为什么要特地加这个而不进行下标判断呢,原因是使用这个会为代码带来极大的方便,后文有讲。

如123   就变成了 $#1#2#3#

mp数组(这个我就不知道是啥简称了): 用于储存以ma中每一个元素为中心的最长回文串的半径,1起步(自己都算一个)

如 #1#  则 mp[0]=1    mp[1]=2

众所周知, 假如需要在O(n)的时间内查找一个字符串的最长回文子串,那么一定需要在遍历的时候一边处理,也预示着需要用之前所处理出来的结果。那么这时候我们就开始顺利成章的假设,假设我已经知道了 mp[0~i](不包括i),那如何利用这一已知条件呢?

先看看代码:

for (int i = 0; i < l; i++) { // i: 表示现在正在处理的那个子串中心
		mp[i] = mx > i ? min(mp[id*2 - i], mx - i) : 1;
		//假如子串存在于最大半径之内,那么直接就可以利用之前匹配到的信息,否则只能从新来了
		while (ma[i + mp[i]] == ma[i - mp[i]]) mp[i]++;
		if (i + mp[i] > mx) {//更新最大覆盖到的半径
			mx = i + mp[i];
			id = i;
		}
		maxx = maxx < mp[i] ? mp[i] : maxx;
	}

为了最大化利用已知条件,我们引入两个变量,id和mx,mx指的是0~i中最大的(id+mp[id]),指的是我已知回文串最能够得着右边的。

因为id的回文串是已经知道的,那么假如i在id的回文串半径之内,我们就可以在id的另外一边对称的地方,也就是2*id-i这个地方得到mp[i]的一部分回文串信息,我们就不需要再重复匹配这一部分了,可以直接让mp[i]=mp[2*id-i],但是此时需要注意,假如i+mp[i]超过了 (id+mp[id]),也就是我已知回文串最能够得着右边的那个地方,由于再往右就已经是未知了,不能保证依然是对称,所以这个时候需要将mp[i]赋值为mx-i ,然后再继续往下找

假如i不在id的回文串半径内呢,那么只能朴素匹配了,将mp[i]赋值为1慢慢找吧。

噢对了最后说一下为什么开头加入'$'会方便一点吧,可以看到查找回文串的代码是:

while (ma[i + mp[i]] == ma[i - mp[i]]) mp[i]++;

也就是在开头加入一个整个字符串都不会出现的字符那么程序必然在这里跳出循环,就不需要每次都判断下标(作为一个小小的加速吧)

最后是这道题的代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2e6 + 7;
char s[maxn];
char ma[maxn]; // 马拉车字符串
int mp[maxn]; // 记录最长回文串 这个数组-1就是答案
void Manacher(int cnt) {
	int maxx = 0;
	int l = 0; // l:新数组长度
	ma[l++] = '$';
	ma[l++] = '#';
	int end = strlen(s);
	for (int i = 0; i < end; i++) {
		//scanf("%c", &ma[l++]);
		ma[l++] = s[i];
		ma[l++] = '#';
	}
	ma[l++] = 0;
	int mx = 0, id = 0; // mx:最大半径能到的地方 id:最大半径中心
	for (int i = 0; i < l; i++) { // i: 表示现在正在处理的那个子串中心
		mp[i] = mx > i ? min(mp[id*2 - i], mx - i) : 1;
		//假如子串存在于最大半径之内,那么直接就可以利用之前匹配到的信息,否则只能从新来了
		while (ma[i + mp[i]] == ma[i - mp[i]]) mp[i]++;
		if (i + mp[i] > mx) {//更新最大覆盖到的半径
			mx = i + mp[i];
			id = i;
		}
		maxx = maxx < mp[i] ? mp[i] : maxx;
	}
	printf("Case %d: %d\n", cnt, maxx-1);
}
int main() {
	int cnt = 0;
	while (scanf("%s", s)) {
		//if (s == "END") break;
		if (s[0] == 'E') break;
		else {
			Manacher(++cnt);
		}
	}
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值