马拉车算法 O(n)复杂度内处理回文

Holidays are almost over and our dear friend Mr. Potato Head wants to enjoy his last days of vacations with different fun activities like solving equations, calculating areas of figures, among others.

Currently, he is playing with different strings, although he finds that most of strings are boring non-palindromic strings. That is why Mr. Potato Head will transform any string into a palindrome inserting characters at the end of the corresponding string.

However, Mr. Potato Head does not want to spend his lasts days of holidays only inserting characters in strings, so he will insert the minimum possible of characters to convert the boring non-palindromic string into a fun palindromic one.

Can you guess the fun strings Mr. Potato Head created from boring ones?

Input
Input consists of a single line with a non-empty string without spaces.

The length of the string is at most $ 5000 5000 5000$.

Output
Print one single line with the string after the changes of Mr. Potato Head.

Examples
Input
helloworld
Output
helloworldlrowolleh
Input
anitalavalatina
Output
anitalavalatina
Note
A palindrome is a string that reads the same backwards as forwards

题目大致意思是只能在字符串后面插入字母,问最少插入次数使他成为回文串,思路是用马拉车算法找出每个位置的最大半径,如果半径加上他的位置刚好等于末尾,就记录这个位置,再输出原先字符串+上不重复的字符串的反向。记得用空格,因为题目说里面不含空格,N开两倍,因为要马拉车要扩增一倍,p[i]=mx>i?min(p[2*id-i],mx-i):1;马拉车算法的精髓就是这一句,id代表最大对称点,mx代表能向右延伸的最大位置,2*id-i代表i对于id的对称点,如果,i在mx里面的话,如果对称点的对称半径没有超过i到mx的距离,就用它的,否则用mx-i代替,不在mx里就把p[i]换成1,老老实实去暴力能否扩增,mx记得更新。P[]数组代表每个点的最大半径(算上自己),mx不含在最大回文字符串里面,所以mx-i不用加一,最后最长的回文串是len-1,一般初始化string +"@“和”#"就行了,

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
string s;
const	int N=5010;
int p[N*2];	
string t;
string malache()
{

	t+=' ';
	t+=' ';
	for(int i=0;i<s.size();i++)
	{
		t+=s[i];
		t+=' ';
	}
	int id=0,mx=0,pos=0,len=0;
	for(int i=1;i<t.length();i++)
	{
		p[i]=mx>i?min(p[2*id-i],mx-i):1;
		while(t[i-p[i]]==t[i+p[i]])	++p[i];
		if(p[i]+i>mx)
		{
			mx=p[i]+i;
			id=i;
		}
		if(p[i]>len)
		{
			len=p[i];
			pos=i;
		}
	}
	return s.substr((pos-len)/2,len-1);
}
int main()
{
	cin>>s;
	string ans=malache();
	int pos=0;
	cout<<t<<endl;
	for(int i=1;i<t.size();i++)
	if(i+p[i] -1==t.size()-1)  //-1是因为p[i]长度还包括了自身
	{
		pos=i;
		break;
	}
;
}
全部评论

相关推荐

10-28 11:04
已编辑
美团_后端实习生(实习员工)
一个2人:我说几个点吧,你的实习经历写的让人觉得毫无含金量,你没有挖掘你需求里的 亮点, 让人觉得你不仅打杂还摆烂。然后你的简历太长了🤣你这个实习经历看完,估计没几个人愿意接着看下去, sdk, 索引这种东西单拎出来说太顶真了兄弟,好好优化下简历吧
点赞 评论 收藏
分享
听说改名字就能收到offer哈:Radis写错了兄弟
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务