回文表示字符串正向和反向是相同的。例如a, aba, abccba
一、暴力法
最容易想到的就是暴力破解,求出每一个子串,之后判断是不是回文,找到最长的那个。
求每一个子串时间复杂度O(N^2), 判断子串是不是回文O(N),两者是相乘关系,所以时间复杂度为O(N^3)。
二、动态规划
下面介绍动态规划的方法,使用动态规划可以达到最优的 O(n2) 复杂度。
令 dp[i][j] 表示 S[i] 至 S[j] 所表示的子串是否是回文子串,是则为 1,不是则为 0。这样根据 S[i] 是否等于 S[j] ,可以把转移情况分为两类:
- 若 S[i] == S[j],那么只要 S[i+1] 至 S[j-1] 是回文子串,S[i] 至 S[j] 就是回文子串;如果S[i+1] 至 S[j-1] 不是回文子串,则 S[i] 至 S[j] 也不是回文子串。
- 若 S[i] != S[j],那么 S[i] 至 S[j] 一定不是回文子串。
根据递推写法从边界出发的原理,注意到边界表示的是长度为 1 和 2 的子串,且每次转移时都对子串的长度减了 1,因此不妨考虑按子串的长度和子串的初始位置进行枚举,即第一遍将长度为 3 的子串的 dp 值全部求出,第二遍通过第一遍结果计算出长度为 4 的子串的 dp 值
public class LongestPalindromicSubstring {
public String longestPalindrome(String s)
{
int n = s.length();
boolean dp[][] = new boolean[n][n];
int maxlen = 1; //保存最长回文子串长度
int start = 0; //保存最长回文子串起点
for(int i = 0; i < n; ++i)
{
for(int j = 0; j <= i; ++j)
{
if(i - j < 2)//包含了i=j和i-j=1的情况
{
dp[j][i] = (s.charAt(i) == s.charAt(j));
}
else
{
dp[j][i] = (s.charAt(i) == s.charAt(j) && dp[j + 1][i - 1]);
}
if(dp[j][i] && maxlen <= i - j + 1)//j到i之间的子串是回文子串
{
maxlen = i - j + 1;
start = j;
}
}
}
return s.substring(start, start + maxlen);
}
public static void main(String[] args) {
LongestPalindromicSubstring longestPalindromicSubstring = new LongestPalindromicSubstring();
System.out.println(longestPalindromicSubstring.longestPalindrome("QATZJUJZTA"));
}
}
三、中心扩展法
中心扩展就是把给定的字符串的每一个字母当做中心,向两边扩展,这样来找最长的子回文串。算法复杂度为O(N^2)。
需要考虑两种情况:
长度为奇数的回文串,比如a, aba, abcba
长度为偶数的回文串,比如aa, abba
public String longestPalindrome2(String s)
{
int len = s.length();
int maxlen = 1;
int start = 0;
for(int i = 0; i < len; i++)//求长度为奇数的回文串
{
int j = i - 1, k = i + 1;//j和k分别是i的两边
while(j >= 0 && k < len && s.charAt(j) == s.charAt(k))
{
if(k - j + 1 > maxlen)
{
maxlen = k - j + 1;
start = j;
}
j--;
k++;
}
}
for(int i = 0; i < len; i++)//求长度为偶数的回文串
{
int j = i, k = i + 1;//奇数和偶数的区别在于j的初始值
while(j >= 0 && k < len && s.charAt(j) == s.charAt(k))
{
if(k - j + 1 > maxlen)
{
maxlen = k - j + 1;
start = j;
}
j--;
k++;
}
}
return s.substring(start, start + maxlen);
}
四、Manacher算法
Manacher算法的时间复杂度为O(N),具体可参考:
https://blog.csdn.net/qq_32354501/article/details/80084325
https://www.cnblogs.com/grandyang/p/4475985.html
https://www.jianshu.com/p/c82cada7e5b0
https://www.cnblogs.com/coderJiebao/p/Algorithmofnotes30.html