对于一般的回文子串的计算方法枚举每一个字符s[i]作为回文串的中心,然后分为奇数回文串和偶数回文串来进行遍历两端,算法复杂度O(n^2)
int palindromeString(const char *s)
{
int len = strlen(s);
int mx1, mx2, ans = 0;
REP(i, len)
{
mx1 = 1;
for(int j = 1; i - j >= 0 && i + j < len && s[i - j] == s[i + j]; ++j) //回文串为奇数
mx1 += 2;
mx2 = 0;
for(int j = 0; i - j >= 0 && i + j + 1 < len && s[i] == s[i + 1] && s[i - j] == s[i + j + 1]; ++j)
mx2 += 2;
ans = max(ans, max(mx1, mx2));
}
return ans;
}
该算法是O(n)的复杂度,对于任意字符串例如abc首先先变成#a#b#c#的形式避免了奇数回文和偶数回文的区别,然后用maxRight记录以s[pos]为中心的回文串所能延伸的最远位置,RL[i]记录以s[i]为中心的回文串到达的最远位置。
int manarcher(const char *s)
{
char tmp[2 * MAX];
int RL[2 * MAX], ans = 0;
int maxRight = 0, pos = 0, len = 2 * strlen(s) + 1;
REP(i, len)
{
if(i & 1) tmp[i] = s[i / 2];
else tmp[i] = '#';
}
tmp[len] = '\0';
REP(i, len)
{
if(i < maxRight)
RL[i] = min(RL[2 * pos - i], maxRight - i);
else
RL[i] = 1;
while(i - RL[i] >= 0 && i + RL[i] < len && tmp[i - RL[i]] == tmp[i + RL[i]])
RL[i]++;
if(i + RL[i] - 1 > maxRight)
{
maxRight = i + RL[i] - 1;
pos = i;
}
ans = max(ans, RL[i]);
}
return ans - 1;
}