Manacher算法
Manacher算法是一种用于查找字符串中最长回文子串的高效算法,它的时间复杂度为O(n)
算法维护一个数组P,其中P[i]表示以位置i为中心的最长回文串的半径
Manacher算法利用了回文串的对称性来加速搜索过程。如果当前考虑的位置i在之前找到的最长回文串的范围内,那么可以利用这个回文串的对称性来确定i的位置的回文半径的初始值。如果i的位置超出了之前回文串的范围,那么需要从i的位置开始进行暴力匹配来确定回文半径
在算法执行过程中,会维护一个最右端点R,它表示当前找到的最长回文串的右端点。每次找到一个新的回文串时,都会更新R的位置
Manacher 算法可以计算以s[i](或者s[i] 和 s[i+1])为回文中心的最长回文子串的长度。
此外,还可以:
- 判断任意子串是否为回文串。
- 计算从𝑠[𝑖] 开始的最长回文子串的长度。
- 计算以𝑠[𝑖] 结尾的最长回文子串的长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class Manacher { public int[] p; private String s; private char[] t; public Manacher(String s) { this.s = s; preprocess(); p = new int[t.length]; int center = 0, right = 0; for (int i = 1; i < t.length-1; i++) { int mirror = 2*center - i; if (right > i) p[i] = Math.min(right - i, p[mirror]); while (t[i + (1 + p[i])] == t[i - (1 + p[i])]) p[i]++; if (i + p[i] > right) { center = i; right = i + p[i]; } } } private void preprocess() { t = new char[s.length()*2 + 3]; t[0] = '$'; t[s.length()*2 + 2] = '@'; for (int i = 0; i < s.length(); i++) { t[2*i + 1] = '#'; t[2*i + 2] = s.charAt(i); } t[s.length()*2 + 1] = '#'; } }
|
无注释模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class Manacher { public int[] p; private String s; private char[] t; public Manacher(String s) { this.s = s; preprocess(); p = new int[t.length]; int center = 0, right = 0; for (int i = 1; i < t.length-1; i++) { int mirror = 2*center - i; if (right > i) p[i] = Math.min(right - i, p[mirror]); while (t[i + (1 + p[i])] == t[i - (1 + p[i])]) p[i]++; if (i + p[i] > right) { center = i; right = i + p[i]; } } } private void preprocess() { t = new char[s.length()*2 + 3]; t[0] = '$'; t[s.length()*2 + 2] = '@'; for (int i = 0; i < s.length(); i++) { t[2*i + 1] = '#'; t[2*i + 2] = s.charAt(i); } t[s.length()*2 + 1] = '#'; } }
|