131. 分割回文串(Medium)/ 132. 分割回文串 II(Hard)/ 1278. 分割回文串 III(Hard)/ 1745. 回文串分割 IV(Hard)

在这里插入图片描述

class Solution:
    def partition(self, s: str) -> List[List[str]]:
        n = len(s)
        # dp[i][j]表示s[i..j]是否为回文串,其中空串、单个字符均为回文串
        dp = [[True] * n for _ in range(n)]

        # 从后往前遍历,确定哪些子串为回文串
        for i in range(n - 1, -1, -1):
            for j in range(i + 1, n):
                # dp[i][j]表示s[i..j]为回文串:
                # 当且仅当s[i]与s[j]相同 且 s[i+1..j-1]为回文串
                dp[i][j] = (s[i] == s[j]) and dp[i + 1][j - 1]

        res = []
        ans = []

        def dfs(i):
            # 下标达到n,表示遍历完所有字符,则记录下当前的结果
            if i == n:
                res.append(ans[:])
                return
            
            # 使用回溯法来获取s[i]到s[n-1]中所有的回文串组合
            for j in range(i, n):
                if dp[i][j]:
                    ans.append(s[i:j+1])
                    dfs(j + 1)
                    ans.pop()

        dfs(0) # 从下标0开始遍历

        return res

在这里插入图片描述

132. 分割回文串 II

在这里插入图片描述

class Solution:
    def minCut(self, s: str) -> int:
        n = len(s)
        # g[i][j]表示s[i..j]是否为回文串,其中空串、单个字符均为回文串
        g = [[True] * n for _ in range(n)]

        # 从后往前遍历,确定哪些子串为回文串
        for i in range(n - 1, -1, -1):
            for j in range(i + 1, n):
                # g[i][j]表示s[i..j]为回文串:
                # 当且仅当s[i]与s[j]相同 且 s[i+1..j-1]为回文串
                g[i][j] = (s[i] == s[j]) and g[i + 1][j - 1]

        # dp[i]表示字符串的前缀子字符串s[0..i]的最少分割次数
        dp = [float("inf")] * n
        for i in range(n):
            # 若s[0..i]本身就是回文串,则无需分割,即分割次数为0
            if g[0][i]:
                dp[i] = 0
            # 若s[0..i]不是回文串,则考虑s[0..i]中是否存在某一个子串s[j+1..i]是回文串,
            # 若存在s[j+1..i]是回文串,那么f[i]就可以从f[j]附加1次额外的分割次数转移而来
            else:
                for j in range(i):
                    if g[j + 1][i]:
                        dp[i] = min(dp[i], dp[j] + 1)
        
        return dp[n - 1]

在这里插入图片描述

1278. 分割回文串 III

在这里插入图片描述

class Solution:
    def palindromePartition(self, s: str, k: int) -> int:
        # 表示将s[i..j]子串变成回文串,最少需要修改的字符数,使用双指针来计算
        def cost(l, r):
            ret, i, j = 0, l, r
            while i < j:
                ret += (0 if s[i] == s[j] else 1)
                i += 1
                j -= 1
            return ret
        
        n = len(s)
        f = [[10**9] * (k + 1) for _ in range(n + 1)]
        f[0][0] = 0
        for i in range(1, n + 1):
            # j表示分割多少次
            for j in range(1, min(k, i) + 1):
                if j == 1:
                    f[i][j] = cost(0, i - 1)
                else:
                    # 枚举第 j 个回文串的起始位置 m
                    for m in range(j - 1, i):
                        f[i][j] = min(f[i][j], f[m][j - 1] + cost(m, i - 1))
        
        return f[n][k]

在这里插入图片描述

1745. 回文串分割 IV

在这里插入图片描述

class Solution:
    def checkPartitioning(self, s: str) -> bool:
        n = len(s)
        dp = [[False] * n for _ in range(n)]
        
        # 单个字符一定为回文串
        for i in range(n):
            dp[i][i] = True
        
        # 区间DP时此处i以倒序遍历
        for i in range(n-2,-1,-1):
            for j in range(i+1,n):
                # 若为2个字符的回文串,则只需考虑这2个字符是否相同
                if j == i+1:
                    dp[i][j] = (s[i] == s[j])
                # 否则还需考虑s[i+1...j-1]是否为回文串
                else:
                    dp[i][j] = (s[i] == s[j]) and dp[i+1][j-1]
        
        # 判断s[0...i], s[i+1...j], s[j...n-1]是否为回文串
        for i in range(0,n-2):
            # 若前i个字符的组成的子字符串s[0...i]不是回文串,则跳过
            if not dp[0][i]:
                continue
            
            # 判断s[i+1...j], s[j...n-1]是否为回文串
            for j in range(i+1,n-1):
                if dp[i+1][j] and dp[j+1][n-1]:
                    return True
                    
        return False
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
动态规划方法可以用来解决分割回文串的问题。可以根据给定的字符串s,使用动态规划找到所有可能的回文子串。 首先,我们可以定义一个二维数组dp,其中dp[i][j]表示字符串s从索引i到j的子串是否是回文串。对于任意的i和j,如果s的第i个字符和第j个字符相等,并且s的第i+1个字符到第j-1个字符是回文串,则dp[i][j]为true。 然后,我们可以使用动态规划填充dp数组。我们可以从字符串s的末尾开始遍历,每次遍历一个字符。对于每个索引i,我们再从i开始向右遍历,直到字符串的末尾。对于每个索引i和j,我们检查字符串s从索引i到j是否是回文串。如果是回文串,则将这个子串添加到结果集中,并继续向右遍历,搜索下一个可能的回文子串。 最后,当我们遍历完整个字符串s时,我们就可以得到所有可能的分割方案。每个分割方案都是由一组回文子串组成的。 下面是一个使用动态规划的实现示例代码: ```cpp class Solution { public: vector<vector<string>> partition(string s) { vector<vector<string>> result; vector<string> path; vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false)); backtracking(s, 0, path, result, dp); return result; } void backtracking(string const& s, int startIndex, vector<string>& path, vector<vector<string>>& result, vector<vector<bool>>& dp) { if (startIndex >= s.size()) { result.push_back(path); return; } for (int i = startIndex; i < s.size(); i++) { if (s[startIndex == s[i && (i - startIndex <= 2 || dp[startIndex + 1][i - 1])) { dp[startIndex][i = true; path.push_back(s.substr(startIndex, i - startIndex + 1)); backtracking(s, i + 1, path, result, dp); path.pop_back(); } } } }; ``` 这是一个基于回溯和动态规划的算法,它可以找到字符串s所有可能的分割方案,使得每个子串都是回文串。你可以根据自己的需求使用这个算法来解决分割回文串的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [131. 分割回文串 回溯 c++](https://blog.csdn.net/qq_39993896/article/details/127132759)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [LeetCode-分割回文串(C++)](https://blog.csdn.net/weixin_42817333/article/details/125468202)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值