题目(回文子串的个数)
— 中心扩展:
给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
回文字符串 是正着读和倒过来读一样的字符串。
子字符串 是字符串中的由连续字符组成的一个序列。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
解析:
我们观察到回文中心的两侧互为镜像。因此,回文可以从它的中心展开,并且只有 2n - 1 个这样的中心
你可能会问,为什么会是 2n - 1 个,而不是 n 个中心?
解释如下:
因为回文的中心要区分单双。
假如回文的中心为 双数,例如 abba,那么可以划分为 ab bb ba,对于n长度的字符串,这样的划分有 n-1 种。
假为回文的中心为 单数,例如 abcd, 那么可以划分为 a b c d, 对于n长度的字符串,这样的划分有 n 种。
代码:
class Solution {
public int countSubstrings(String s) {
int n = s.length();
int ans = 0;
// 要扫描2n-1个中心
for(int k = 0; k<n*2-1; k++){
int i = k/2;
int j = k/2 + k%2;
while(i>=0&&j<n&&s.charAt(i)==s.charAt(j)){
i--;
j++;
ans++;
}
}
return ans;
}
}
—中心扩展(最长回文子串):
class Solution {
public String longestPalindrome(String s) {
int max = 0,left = 0,right = 0;
int n = s.length();
String s1 = "";
for(int k = 0; k<2*n-1; k++){
int i = k/2;
int j = k/2 + k%2;
while(i>=0&&j<n&&s.charAt(i)==s.charAt(j)){
i--;
j++;
}
if(max<j-i-1){
max = j-i-1;
left = i+1;
right = j;
}
}
s1 = s.substring(left,right);
return s1;
}
}
—动态规划(最长回文子串)
解析:
a[i] [j]表示从i到j是否为回文串
先初始化数组,把a[i] [i]初始化为true,因为单个字符串认定为回文,之后以2为长度(l),找到左边界i,找到右边界j,判断左右边界是否相等如果不相等,直接置为false,如果相等----两种情况:
- 长度为2,则置为true
- 长度大于2,则置为a[i+1] [j-1],也就是左右都向中走一位,即这一级是否为回文串取决于上一级是否为回文串,如:a…a是否为回文取决于…是否是回文
然后用max记录每次的最大长度,begin记录左边界的位置
代码:
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
char[] chars = s.toCharArray();
int max = 1;
int begin = 0;
boolean[][] a = new boolean[n][n];
for(int i = 0; i<n; i++){
a[i][i] = true;
}
for(int l = 2; l<=n; l++){
for(int i = 0; i<n; i++){
int j = l+i-1;
if(j>=n){
break;
}
if(chars[i]!=chars[j]){
a[i][j]=false;
}else{
if(j - i < 3){
a[i][j] = true;
}else{
a[i][j] = a[i+1][j-1];
}
}
if(a[i][j]&& j-i+1 > max){
max = j-i+1;
begin = i;
}
}
}
return s.substring(begin, begin + max);
}
}