最大回文子串相关

最大回文子串

法一:动态规划:边界和状态转换方程
法二:中心扩展

//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]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值