https://leetcode.cn/problems/palindromic-substrings/description/

这段代码是一个用于计算给定字符串中回文子串数量的解决方案。代码中定义了一个Solution类,其中包含一个countSubstrings方法,该方法接收一个字符串s作为参数,并返回回文子串的数量。
代码首先将输入字符串s转换为字符数组chars,并获取字符串长度len。然后创建一个二维布尔数组dp,用于记录字符串中各个子串是否为回文串。接着初始化一个变量result用于存储回文子串的数量。
代码使用动态规划的思想,在双重循环中遍历字符串中所有可能的子串。对于每个子串,检查其首尾字符是否相同,如果相同则根据不同情况更新result和dp数组:
最终返回result作为回文子串的总数量。
这段代码实现了一个计算给定字符串中回文子串数量的功能。以下是代码的解释:
这段代码通过动态规划的方法计算字符串中的回文子串数量,时间复杂度为 O ( n 2 ) O(n^2) O(n2),其中n为字符串s的长度。
这段代码是一个Java解决方案类,其中的方法countSubstrings用于计算给定字符串s中的回文子串数量。
s是否为空或长度小于1,若是则直接返回0。s的所有可能中心点(总共有
2
×
len
−
1
2 \times \text{len} - 1
2×len−1个中心点),向两边扩散来判断是否是回文子串。left == right,另一种是right = left + 1,这两种情况的回文中心不同。ans并继续向两边扩散。ans。这段代码利用中心扩散法来快速计算回文子串的数量,通过遍历所有可能的中心点,从中心向两边扩散,判断是否是回文串。
这段代码是一个解决回文子串数量问题的算法。下面是对代码的清晰、简洁和易读的解释:
整体来说,这段代码利用了中心拓展法来统计给定字符串中的回文子串数量。
package 代码随想录.动态规划;
public class _647回文子串_dp法 {
/**
*
* @param s
* @return
*/
public int countSubstrings(String s) {
// 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
// 按下标为唯一标识符,不考虑字符的重复性,同时要保证是连续的。
char[] chars = s.toCharArray();
int len_chars = chars.length;
boolean [][] dp = new boolean[len_chars][len_chars];
int result = 0;
for (int i = len_chars - 1;i>=0;i--){
for (int j = i;j<len_chars;j++){
if (chars[i] == chars[j]){
if (j - i<=1){
result++;
dp[i][j] = true;
}else if (dp[i+1][j-1]){
result++;
dp[i][j] = true;
}
}
}
}
return result;
}
}
package 代码随想录.动态规划;
public class _647回文子串_简易dp法 {
/**
*
* @param s
* @return
*/
public int countSubstrings(String s) {
// 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
// 按下标为唯一标识符,不考虑字符的重复性,同时要保证是连续的。
char[] chars = s.toCharArray();
int len_chars = chars.length;
boolean [][] dp = new boolean[len_chars][len_chars];
//也可以直接调s.length(),s.chatAt(i)方法直接获取。
int res = 0;
for (int i = s.length() - 1;i>=0;i--){
for (int j = i;j<s.length();j++){
if (s.charAt(i) == s.charAt(j) && (j-i <= 1 || dp[i+1][j-1])){
res++;
dp[i][j] = true;
}
}
}
return res;
}
}
package 代码随想录.动态规划;
public class _647回文子串_中心扩展法 {
/**
*
* @param s
* @return
*/
public int countSubstrings(String s) {
// 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
// 按下标为唯一标识符,不考虑字符的重复性,同时要保证是连续的。
int len_s = s.length(),res = 0;
if (s == null || len_s < 1 ){
return 0;
}
//总共有【2 * len - 1】个中心店
for (int i = 0; i < 2 * len_s - 1; i++){
//通过遍历每个回文中心,向两边扩散,并判断为是否回文字串
//有两种情况,left == right ,,, right = left + 1 ,,,这两种回文中心是不一样的。
int left = i/2,right = left + i % 2;
while (left >= 0 && right < len_s && s.charAt(left) == s.charAt(right)){
//如果当前是一个回文串,则记录效量
res++;
left--;
right++;
}
}
return res;
}
}
package 代码随想录.动态规划;
public class _647回文子串_Manacher算法 {
/**
*
* @param s
* @return
*/
public int countSubstrings(String s) {
// 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
// 按下标为唯一标识符,不考虑字符的重复性,同时要保证是连续的。
int len_s = s.length();
StringBuilder sb_s = new StringBuilder("s#");
for (int i = 0; i < len_s; i++) {
sb_s.append(s.charAt(i));
sb_s.append("#");
}
int len_sb_s = sb_s.length();
sb_s.append('!');
int [] dp = new int [len_sb_s];
int iMax = 0,rMax = 0,res = 0;
for (int i = 1;i<len_sb_s;i++){
//初始化 f[i]
dp[i] = i <= rMax ? Math.min(rMax - i + 1,dp[2*iMax - i]) : 1;
//中心扩展
while (sb_s.charAt(i + dp[i]) == sb_s.charAt(i - dp[i])){
++dp[i];
}
//动态维护iMax 和 rMax
if (i + dp[i] - 1 > rMax){
iMax = i;
rMax = i + dp[i] - 1;
}
//统计答案,当前贡献为(f[i] - 1)/2 向上取整
res += dp[i] / 2;
}
return res;
}
}