Manacher 最长回文子串

用途

  • 求最长回文串, 过程中更新 m a x ( M a x l e n , R L [ i ] − 1 ) max(Maxlen,RL[i]-1) max(MaxlenRL[i]1)
  • 求回文串的数量, ∑ i = 0 l e n R L [ i ] 2 \sum_{i=0}^{len}\frac{RL[i]}{2} i=0len2RL[i]

R L [ i ] RL[i] RL[i] :关于i的回文半径
M a x R i g h t MaxRight MaxRight:pos能到达的最右端的位置
M a x L e n MaxLen MaxLen:记录答案

  • 首先在原字符串中插入字符“#”
    例如:“abba” -> "#a#b#b#a#"这样不影响回文串,好处是可以同时解决长度为奇偶的字符串,而且(回文半径 - 1)就是原来的回文串长度
  • 问题转化为如何高效的求每个字符的回文串半径,当我们知道pos能到达的最右端位置 M a x R i g h t MaxRight MaxRight,我们继续向后枚举字符串求它的回文半径,我们关心的是i这个位置是在MaxRight的左边还是右边, 在左边分为两种情况,右边一种情况。
  • 求出来最小值之后再向两边扩展得到最长的回文半径, 然后更新 p o s pos pos M a x R i g h t MaxRight MaxRight

int RL[maxn << 1];
int Manacher(string s) {
	string t;
	for (int i = 0; i < (int)s.size(); ++i) {
   		t += s[i];
   		t += '#';
   	}
   	s = "#" + t;
   	int MaxRight = 0, pos = 0, MaxLen = 0;
   	for (int i = 0; i < (int)s.size(); ++i) {
   		if (i < MaxRight)	RL[i] = min(RL[2 * pos - i], MaxRight - i + 1); // 好多这里写的是 MaxRight - i,个人感觉根据算法思想应该+1计算长度。
   		else 	RL[i] = 1;
   		int l = i - RL[i];
   		int r = i + RL[i];
   		while (l >= 0 && r < (int)s.size() && s[l] == s[r])	{
   			RL[i] += 1;
   			l = i - RL[i];
   			r = i + RL[i];
   		}
   		if (RL[i] + i - 1 > MaxRight) {
   			MaxRight = RL[i] + i - 1;
   			pos = i;
   		}
   		MaxLen = max(MaxLen, RL[i]);
   	}
   	return MaxLen - 1;
}
int RL[maxn << 1];
char s[maxn], t[maxn << 1];
int Manacher(char *s) {
	if (s[strlen(s) - 1] == '\n')	s[strlen(s) - 1] = '\0';
	int lens = strlen(s), len = 0;
	t[len++] = '#';
	for (int i = 0; i < lens; ++i) {
   		t[len++] = s[i];
   		t[len++] = '#';
   	}
   	int MaxRight = 0, pos = 0, MaxLen = 0;
   	for (int i = 0; i < len; ++i) {
   		if (i < MaxRight)	RL[i] = min(RL[2 * pos - i], MaxRight - i + 1); // 好多这里写的是 MaxRight - i,个人感觉根据算法思想应该+1计算长度。
   		else 	RL[i] = 1;
   		int l = i - RL[i];
   		int r = i + RL[i];
   		while (l >= 0 && r < len && t[l] == t[r])	{
   			RL[i] += 1;
   			l = i - RL[i];
   			r = i + RL[i];
   		}
   		if (RL[i] + i - 1 > MaxRight) {
   			MaxRight = RL[i] + i - 1;
   			pos = i;
   		}
   		MaxLen = max(MaxLen, RL[i]);
   	}
   	return MaxLen - 1;
}

你可能感兴趣的:(算法模板)