最长回文子串
此博客不会讲太多原理的东西,主要是平时复习巩固的时候用一下
如果是初学者,可见大佬链接:
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;
}