最大回文子串
法一:动态规划:边界和状态转换方程
法二:中心扩展
//1.动态规划
public static String longestPalindrome(String s) {
int n = s.length();
if (n < 2) return s;
int maxLen = 1;
String res = s.substring(0, 1);
boolean[][] dp = new boolean[n][n];
//左边界一定小于右边界,因此从右边界开始
for (int r = 1; r < n; r++) { //表示右边界
for (int l = 0; l < r; l++) { //表示左边界
// 区间应该慢慢放大
// 状态转移方程:如果头尾字符相等并且中间也是回文
// 在头尾字符相等的前提下,如果收缩以后不构成区间(最多只有 1 个元素),直接返回 True 即可
// 否则要继续看收缩以后的区间的回文性
if (s.charAt(l) == s.charAt(r) && ((r - l) <= 2 || dp[l + 1][r - 1])) {
dp[l][r] = true;
if (r - l + 1 > maxLen) {
maxLen = r - l + 1;
res = s.substring(l, r + 1);
}
}
}
}
return res;
}
""
dp[i][j],表示第i个字符至第j个字符组成的子串是否为回文子串。
当字符串i所在的字符等于字符串j所在的字符,并且它的内部(dp[i+1][j-1])为回文那么dp[i][j]为true。
因为这样的规律,我们要保证判断dp[i][j]的时候dp[i+1][j-1]已经判断,所以我们遍历采用i降序j升序的嵌套遍历的方式
"""
def longHuiwen(string):
n=len(string)
dp=[[1 for _ in range(n)] for _ in range(n)] #默认初始为1
start=0
max_len=1
for i in range(n-2,-1,-1):#i降序
dp[i][i]=1#设置1
for j in range(i+1,n):
dp[i][j]=(string[i]==string[j]) and ((j-i)<3 or dp[i+1][j-1])#状态转移,j-i>3:因为当字符串为3时aba肯定时回文串
if dp[i][j] and max_len<=j-i+1:# 保留最大值,<保留的为最右端的最长子串;<=最左端的
max_len=j-i+1
start=i
return string[start:max_len+start]
回文子串的个数
注意单个字符的情况
public class Solution14_回文子串 {
/**
* 方法一:中心扩散法
*/
static int ans = 0;
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String s = bf.readLine();
for (int i = 0; i < s.length(); i++) {
//考虑两种情况:aba 和 abba
centerSpread(s, i, i);
centerSpread(s, i, i + 1);
}
System.out.println(ans);
}
//判断回文串的中心扩散法
private static void centerSpread(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left--;
right++;
ans++;
}
}
//方法二:动态规划
private static int dp(String s) {
int n = s.length(), ans = 0;
boolean[][] dp = new boolean[n][n];
for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
dp[i][j] = (s.charAt(i) == s.charAt(j)) && (j - i <= 2 || dp[i + 1][j - 1]);
if (dp[i][j]) ans++;
}
}
return ans;
}
}
def countHuiwen(string):
n=len(string)
count=n
dp=[[1 for _ in range(n)] for _ in range(n)]
print(dp)
for i in range(n-2,-1,-1):
dp[i][i]=1
for j in range(i+1,n):
dp[i][j]=(string[i]==string[j]) and (j-i<3 or dp[i+1][j-1])
if dp[i][j]:
count+=1
return count
暴力破解
while True:
try:
string=input()
n=len(string)
count=len(string)
for i in range(n-1):
for j in range(i+1,n):
if string[i:j+1]==string[i:j+1][::-1]:
count+=1
print(count)
except:
break
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
String str=sc.nextLine();
int n=str.length();
int count=n;
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
if(isHuiwen(str,i,j)) count+=1;
}
}
System.out.println(count);
}
public static boolean isHuiwen(String str,int i,int j){
while(i<j){
if(str.charAt(i)!=str.charAt(j)) return false;
i++;
j--;
}
return true;
}
}
非连续最大回文子串的长度
#字符可不连续选择,dp[i][j]表示i-j个字符的最大回文子串长度
def maxHuiwen(s):
n=len(s)
dp=[[1 for _ in range(n)] for _ in range(n)]
for i in range(n-2,-1,-1):
dp[i][i]=1
for j in range(i+1,n):
if s[i]==s[j]:
dp[i][j]=dp[i+1][j-1]+2
else:
dp[i][j]=max(dp[i+1][j],dp[i][j-1])
return dp[0][n-1]