马拉车(Manachar)——最长回文串
简介
Manachar 算法在 O(n) 时间处理出以字符串中每一个字符为中心的回文串半径。Manacher 算法通过将原字符串每个字符的左右两边都插入一个分隔符的方式,将长度为奇数的回文串和长度为偶数的回文串一起考虑。(分隔符不在原串中出现,一般情况下可以用 # 号代表)
预处理
实现
马拉车的主要思想就是利用回文串两边相同的性质,用已知回文串去推未知回文串。
代码
public class Main
{
public static int solution(String s)
{
int sc = -1, sr = -1, ansCenter = 0, ansLen = 0;
int[] p = new int[2 * s.length() + 1];
StringBuilder str = new StringBuilder();
str.append('#');
for (char ch : s.toCharArray())
str.append(ch + "#");
for (int i = 0; i < str.length(); i++)
{
p[i] = sr > i ? Math.min(p[2 * sc - i], sr - i) : 1;
while (i + p[i] < str.length() && i - p[i] > -1 && str.charAt(i + p[i]) == str.charAt(i - p[i]))
++p[i];
if (sr < i + p[i])
{
sr = i + p[i];
sc = i;
}
if (ansLen < p[i])
{
ansLen = p[i];
ansCenter = i;
}
}
int start = (ansCenter - ansLen + 1) / 2;
System.out.println(s.substring(start, start + ansLen - 1));
return ansLen - 1;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
String s = in.nextLine();
System.out.println(solution(s));
}
}