Manacher's Algorithm 马拉车算法,线性查找一个字符串的最长回文子串

学习自这篇博客, 博主写得非常好, 算法原理请看这篇博客, 而代码实现下面的更明了

int p[100000];
string solve(string s)
{
	string t = "$#";
	for (int i = 0; i < s.length(); i++)
	{
		t += s[i];
		t += '#';
	}
//mx是回文串能延伸到的最右端的位置
//id为能延伸到最右端的位置的那个回文子串的中心点位置
//reslen表最长回文串半径
//rescen为最长回文串中心
	int mx = 0, id = 0, reslen = 0, rescen = 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 (mx < i + p[i])
		{
			mx = i + p[i];
			id = i;
		}
		if (reslen < p[i])
		{
			reslen = p[i];
			rescen = i;
		}
	}
//最长子串的长度是半径减1,起始位置是中间位置减去半径再除以2
	return s.substr((rescen - reslen)/2, reslen - 1);
}
小A的回文串

链接:https://ac.nowcoder.com/acm/contest/549/B

小A非常喜欢回文串,当然我们都知道回文串这种情况是非常特殊的。所以小A只想知道给定的一个字符串的最大回文子串是多少,但是小A对这个结果并不是非常满意。现在小A可以对这个字符串做一些改动,他可以把这个字符串最前面的某一段连续的字符(不改变顺序)移动到原先字符串的末尾。那么请问小A通过这样的操作之后(也可以选择不移动)能够得到最大回文子串的长度是多少。
在这里插入图片描述


#include<iostream>
#include<cmath>
#include<vector>
#include<string>
#include <stdio.h>
#include<algorithm>
#include<functional>
#define rep(a,b) for(int i=a;i<b;i++)
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;

int p[100000];

int solve(string s)
{

	string t = "$#";
	for (int i = 0; i < s.size(); ++i) {
		t += s[i];
		t += "#";
	}
  
    int mx = 0, id = 0, reslen = 0;
	for (int i = 1; i < t.length(); i++)
	{
		p[i] = mx > i ? min(p[id * 2 - i], mx - i) : 1;
		while (t[i + p[i]] == t[i - p[i]]) ++p[i];
		if (mx < i + p[i])
		{
			mx = i + p[i];
			id = i;
		}
		reslen = max(reslen, p[i]);
	}

	return reslen - 1;
}

int main()
{
	ios::sync_with_stdio(false);
	string s;
	cin >> s;
	int len = s.length();
	s += s;
	int res = 0;
	for (int i = 0; i < s.length() - len; i++)
		res = max(res, solve(s.substr(i, len)));
	cout << res;
}

猜你喜欢

转载自blog.csdn.net/qq_40212930/article/details/89398902