最长回文子串——马拉车

最长回文子串

此博客不会讲太多原理的东西,主要是平时复习巩固的时候用一下
如果是初学者,可见大佬链接:
https://www.cnblogs.com/love-yh/p/7072161.html.

p[]数组的求取

p[]用来存res字符串的回文半径,p[i]存res[i]为中心的回文串的半径,通过简单推理可得,p[i]-1就是以s[i]为中心的回文串的长度
1.i<=ri
j是i关于mi对称的点,j=mi*2-i
若p[j]<ri-i,p[i]=p[j],
若p[j]>=ri-i,p[i]=ri-i,超出部分需要一一遍历匹配,直到失配为止,然后更新mi和ri的值
2.i>ri
就只有一一遍历匹配

代码:
#include <iostream>
#include<stdio.h>
#include<vector>
#include<string>
#define me(a,b) memset(a,b,sizeof(a))
using namespace std;

string Manacher(string s)
{
	/*改变字符串*/
	//在字符串内插#,字符串首的$和串尾的\n可防止数组越界
	string res="$#";
	for(int i=0;i<(int)s.size();i++)
	{
		res+=s[i];
		res+="#";
	}
	/*赋初值*/
	vector<int>p(res.size(),0);
	//这个vector的意思是p包含了和res长度相等个数的值为0的元素
	int mi=0,ri=0,maxlen=0,maxpos=0;
	//回文串对应的中心点,该回文串能到大的最右端点的位置
	//最长回文串的长度,最长回文串的中心点
	for(int i=1;i<(int)res.size();i++)
	//i是从1开始的,如果从0开始$就起不到防止数组越界的作用
	{
		p[i]=ri>i?min(p[mi*2-i],ri-i):1;
		while(res[i-p[i]]==res[i+p[i]])
			++p[i];
		if(ri<p[i]+i)
		{
			ri=p[i]+i;
			mi=i;
		}
		if(maxlen<p[i])
		{
			maxlen=p[i];
			maxpos=i;
		}
	}
	return s.substr((maxpos-maxlen)>>1,maxlen-1);
	//截取从(maxpos-maxlen)/2这个位置的点开始的长度为maxlen-1的字符串
}
int main()
{
	string s;//string定义的字符串只能用cin,cout输入输出
	cin>>s;
	s=Manacher(s);
	cout<<s<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值