问题一
给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。
实例
输入: "abc"
输出: 3
解释: 三个回文子串: "a", "b", "c".
方法一
可以发现,回文串特点就是每个回文串都有一个中心点,左右边是对称的,那么我们就可以以中心点为基点,向两边扩散遍历,如果左右的字符相等,那么,就可以认定该子串为一个字符串。回文串长度分奇数偶数,奇数串的中心可以为长度为N的字符串的每一个字符,偶数串的中心可以为长度为N的字符串的每一个间隔,理解为俩字符中间的 |。
代码
class Solution {
public int countSubstrings(String s) {
boolean[][] isHuiWen = new boolean[s.length()][s.length()];
for(int i = 0; i < s.length(); i++){
for(int j = 0; j < s.length(); j++){
isHuiWen[i][j] = false;
}
}
int p,q,m;
//先扫描奇数的
for(m = 0; m < s.length(); m++){
p = q = m;
while(p >= 0 && q < s.length() && s.charAt(p) == s.charAt(q)){
isHuiWen[p][q] = true;
q++;
p--;
}
}
//扫描偶数
for(m = 0; m < s.length(); m++){
p = m;
q = m+1;
while(p >= 0 && q < s.length() && s.charAt(p) == s.charAt(q)){
isHuiWen[p][q] = true;
p--;
q++;
}
}
int num = 0;
for(int i = 0; i < s.length(); i++){
for(int j = 0; j < s.length(); j++){
if(isHuiWen[i][j] == true){
num++;
}
}
}
return num;
}
}
方法二(动态规划)
思路
使用动态规划, dp[i][j] 代表str[i] - str[j]是否是回文子串
考虑单字符和双字符的特殊情况
状态转移方程:dp[i][j] = dp[i+1][j-1] && str[i]==str[j]
代码
class Solution {
public static int countSubstrings(String s) {
boolean[][] dp = new boolean[s.length()][s.length()];
int res = 0;
int i,j; //判断i到之间的字符串是不是回文串
for(j = 0; j < s.length(); j++){ //注意:这里得先遍历j,再遍历i
for(i = j; i >= 0; i--){
if(s.charAt(i) == s.charAt(j) && (j - i < 2 || dp[i+1][j-1])){
dp[i][j] = true;
res++;
}
}
}
return res;
}
public static void main(String[] args) {
String s = "aaa";
System.out.println(countSubstrings(s));
}
}
问题二
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
实例
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
思路
第一步:首先寻找回文子串,思路同问题一相同
第二步:使用low和high记录一下最长回文子串的位置
代码
输入: "babad"
class Solution {
public String longestPalindrome(String s) {
boolean[][] huiwen = new boolean[s.length()][s.length()];
if(s.length() == 0){
return s;
}
int p,q;
int max = 0;
for(int i = 0; i < s.length(); i++){
p = q = i;
while(p >= 0 && q < s.length() && s.charAt(p) == s.charAt(q)){
huiwen[p][q] = true;
p--;
q++;
}
}
for(int i = 0; i < s.length(); i++){
p = i;
q = i + 1;
while(p >= 0 && q < s.length() && s.charAt(p) == s.charAt(q)){
huiwen[p][q] = true;
p--;
q++;
}
}
int low = 0;
int high = 0;
for(int i = 0; i < s.length(); i++){
for(int j = 0; j < s.length(); j++){
if(huiwen[i][j] == true){
if(high - low < j-i){
high = j;
low = i;
}
}
}
}
return s.substring(low,high+1);
}
}