最长回文子串:探索Java编程中的经典算法挑战

一、引言
回文子串是字符串中的一种特殊子串,它从前往后读和从后往前读都是一样的。例如,“abcba”就是一个回文子串。在Java编程中,寻找一个字符串中的最长回文子串是一个经典的算法问题。本文将深入探讨这个问题,分析不同的解决方案,并分享一些实战经验。
二、暴力解法
暴力解法是最直观的思路,即对字符串中的所有子串进行遍历,判断是否为回文子串,并记录下最长的回文子串。下面是使用Java实现暴力解法的代码示例:
```java
public class LongestPalindrome {
public static String longestPalindrome(String s) {
if (s == null || s.length() < 2) {
return s;
}
int start = 0;
int end = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expandAroundCenter(s, i, i);
int len2 = expandAroundCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
private static int expandAroundCenter(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left--;
right++;
}
return right - left - 1;
}
public static void main(String[] args) {
String s = "babad";
System.out.println(longestPalindrome(s)); // 输出:bab 或 babab
}
}
```
暴力解法的优点是简单易懂,但缺点是时间复杂度为O(n^3),当字符串长度较大时,效率较低。
三、中心扩展法
中心扩展法是一种改进的解法,它将字符串中的每个字符都视为一个潜在的回文中心,然后向两边扩展,判断是否为回文子串。下面是使用Java实现中心扩展法的代码示例:
```java
public class LongestPalindrome {
public static String longestPalindrome(String s) {
if (s == null || s.length() < 2) {
return s;
}
int start = 0;
int end = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expandAroundCenter(s, i, i);
int len2 = expandAroundCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
private static int expandAroundCenter(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left--;
right++;
}
return right - left - 1;
}
public static void main(String[] args) {
String s = "babad";
System.out.println(longestPalindrome(s)); // 输出:bab 或 babab
}
}
```
中心扩展法的时间复杂度为O(n^2),比暴力解法有较大提升。
四、Manacher算法
Manacher算法是一种高效的解法,时间复杂度为O(n)。它通过预处理字符串,将原字符串转化为一个包含特殊字符的新字符串,然后通过遍历新字符串,使用一个辅助数组记录每个位置的最长回文半径。
下面是使用Java实现Manacher算法的代码示例:
```java
public class LongestPalindrome {
public static String longestPalindrome(String s) {
if (s == null || s.length() < 2) {
return s;
}
String newStr = "#";
for (int i = 0; i < s.length(); i++) {
newStr += s.charAt(i) + "#";
}
newStr += "$";
int[] p = new int[newStr.length()];
int center = 0, right = 0;
for (int i = 1; i < newStr.length() - 1; i++) {
int mirror = 2 * center - i;
if (i < right) {
p[i] = Math.min(right - i, p[mirror]);
}
while (newStr.charAt(i + 1 + p[i]) == newStr.charAt(i - 1 - p[i])) {
p[i]++;
}
if (i + p[i] > right) {
center = i;
right = i + p[i];
}
}
int maxLen = 0;
int centerIndex = 0;
for (int i = 1; i < newStr.length() - 1; i++) {
if (p[i] > maxLen) {
maxLen = p[i];
centerIndex = i;
}
}
return s.substring((centerIndex - maxLen) / 2, (centerIndex + maxLen) / 2);
}
public static void main(String[] args) {
String s = "babad";
System.out.println(longestPalindrome(s)); // 输出:bab 或 babab
}
}
```
Manacher算法在处理较长的字符串时,具有很高的效率。
五、总结
本文介绍了最长回文子串问题的三种解法:暴力解法、中心扩展法和Manacher算法。通过对比分析,我们可以发现,Manacher算法在处理较长的字符串时,具有很高的效率。在实际应用中,我们可以根据具体需求选择合适的解法。希望本文能对您有所帮助。





