一)简介
回文数:正着和反着读是一样的,例如:abccba;
回文子串:在一个字符串中,一串连续并且正着反着读是一样的字符。
例如:aattyyttdd中,aa、tt、ttyytt、yy、dd都是回文子串。
最长回文子串:在一个字符串中,回文子串最长的一串字符。
备注:每一个单独的字符本身就可以看作是一个回文数。
二)最长回文子串
方式一:暴力法,执行时间复杂度是O(n^3),暂不考虑。
方式二:中心扩展法
原理:假设以每一个字符为中心,围绕该字符向左右两端探测比较。
分析:由于存在奇数的字符串和偶数的字符串,从一个字符扩展,总共有n+n-1个中心。
例如:aabccbad
1)先以第一个a为中心,向左右两边扩展,a的左方没有字符,本身就是回文子串。
2)再以第二个a为中心,向左右两边扩展,不是回文子串。
3)重复用每一个字符向左右两边扩展,只记录最长回文子串的信息。
中心扩展法源码:
/**
* 中心扩展法: 最长回文子串
* @param s
*/
public static String revertSubString(String s) {
if (s == null || s.length() <= 0) {
return null;
}
// 转换成字节数组
char[] ch = s.toCharArray();
int begin = 0; // 开始位置
int end = 0; // 结束位置
for (int i = 0; i < ch.length; i++) {
int len1 = getLength(ch, i, i);
int len2 = getLength(ch, i, i + 1);
int maxLen = Math.max(len1, len2);
// 计算开始位置和结束位置
if (maxLen > end - begin) {
begin = i - (maxLen-1) / 2;
end = i + maxLen / 2;
}
}
// 返回
return s.substring(begin, end + 1);
}
private static int getLength(char[] ch, int left, int right) {
// 左边界要大于等于0,右边界要小于字符串的长度,并且两个要相等,否则会死循环
while (left >= 0 && right < ch.length && ch[left] == ch[right]) {
left--;
right++;
}
// 由于存在奇数的字符串和偶数的字符串,从一个字符扩展,总共有n+n-1个中心
return right - left - 1;
}
方式三:动态规划法
1)先声明一个boolean[][] dp的二维数组,标识回文字符子串的连续路径,是回文数就标识为true。
2)用“i”表示终点,“j”表示起点
若i==j,则dp[i][j]=true;
若i和j是相邻的,则dp[i][j]=true;
若i和j中间只有一个字符,则dp[i][j]=true;
检查dp[j+1][i-1]是否为true,若为true,那么dp[i][j]就是true。
前三条可以合并,即 j−i<=2。
3)记录最长回文子串的信息,并返回。
动态规划法源码:
/**
* 动态规划: 最长回文子串
* @param s
* @return
*/
public static String lcsSubString(String s) {
if (s == null) {
return "";
}
char[] ch = s.toCharArray();
int len = ch.length;
boolean[][] dp = new boolean[len][len];
int maxLen = 0; // 回文子串长度
int start = 0; // 开始位置
int end = 0; // 结束位置
for (int i = 0; i < len; i++) { // i表示终点
int j = i; // j表示起点
while (j >= 0) {
if (ch[i] == ch[j] && (i - j <= 2 || dp[j+1][i-1])) {
dp[j][i] = true; // 如果是回文子串,标识为true
// 最大长度,如果出现长度一样的字符串,取最后一个
if (maxLen <= (i- j + 1)) {
maxLen = (i- j + 1);
start = j; // 开始位置
end = i + 1; // 结束位置
}
}
j--;
}
}
// 返回
return s.substring(start, end);
}
识别二维码关注个人微信公众号
本章完结,待续、欢迎转载!
本文说明:该文章属于原创,如需转载,请标明文章转载来源!