(模板)Manacher算法:线性时间求字符串内回文子串的数量


已通过leetcode647:https://leetcode-cn.com/problems/palindromic-substrings/

void get_d(vector & d, const string & s)
{
	//l r 为维护的最靠右的回文串边界
	int n = s.size(), l = 0, r = -1;
	for(int i = 0; i < n; ++i)
	{
		//在边界内,刚处理完i-1,最差情况是l == r == i-1
		//所以一定i>l,k是初始确定的以i为中心的回文串半径(数量)
		int k = i > r ? 1 : min(d[l + r - i], r - i + 1);
		while(i + k < n && i - k >= 0 && s[i-k] == s[i+k])
			++k;
		d[i] = k--; //循环的条件被k破坏,出来后要k--
		if(i + k > r)
		{
			r = i+k;
			l = i-k;
		}
	}
}

int manacher(const string &s)
{

	int n = s.size();
	//d1[i]为以i为中心的回文串(长度为奇数)数量,
	vector d1(n);
	get_d(d1, s);

	//辅助字符串,统一处理偶数长度的回文串
	string s2(n*2+1, ' ');
	for(int i = 0, j = 1; i < n; ++i, j+=2)
		s2[j] = s[i];

	vector d2(n), d3(2*n+1);
	get_d(d3, s2);
	for(int i = 2, j = 0; j < n; ++j, i+=2)
		d2[j] = (d3[i] - 1)/2;
	
	int sum = 0;
	for(int i = 0; i < n; ++i)
		sum += d1[i] + d2[i];
	return sum;
}