【Leetcode】1147-1912

题目

ps:之后的文章会先把题目链接过来

1147.段式回文<<--

你会得到一个字符串 text 。你应该把它分成 k 个子字符串 $(subtext_1, subtext_2,…, subtext_k) $,要求满足:

\(subtext_i\) 是 非空 字符串
所有子字符串的连接等于 text ( 即\(subtext_1 + subtext_2 + ... + subtext_k == text\) )
对于所有 i 的有效值( 即 1 <= i <= k ) ,$subtext_i == subtext_k - i + 1 $均成立
返回k可能最大值。

  • \(1\leq text.length\leq 1000\)
  • \(text\) 仅由小写英文字符组成

前言

之前做过的题目,现在在做就可以给出一个至少在我看起来更好的代码了

之后也是通过逐步的思考,写出更漂亮和简洁的代码。

思路

题目给定的分割,可以发现一定是首和尾进行对应,那么如果首尾找到了一个符合条件的字符串,那么就可以递归的进行分割。

即,如果我们找到了\(text[:i]==text[-i:]\),这个时候我们就可以递归的进行longestDecomposition(text[i:-i])的调用。

这样我们就找到了递归是如何进行的,此时问题的关键就在于,我们是找到一个i以进行递归还是说需要遍历每种情况之后,选择最优的。
下边进行证明,不需要找出所有的i然后对比选出最优的情况,只需要找到最短或者说最近的符合条件的i即可进行递归。证明如下:

假定在当前所在字符串的头部和尾部分别存在字符串A,B 和 A,B。即整个字符串为AB...AB。
如果在选出A的时候已经找到了符合条件的i,即A==B,此时可以进行递归。

由于A==B,因此如果我们此时选择了A==B,那么后续可以继续选择B==A,这样就将匹配的AB分割为了四个段,而如果我们选择了将AB进行匹配,则得到了2个子字符串,因此找到可以匹配分割的方案总是优于选择后续分割的方案

据此,我们就可以写出最初版的代码

class Solution:
    def longestDecomposition(self, s: str) -> int:
        if len(s)<=1:return len(s)
        for i in range(1,len(s)//2+1):
            if s[:i]==s[-i:]:
                return 2+self.longestDecomposition(s[i:-i])
        return 1

这样的做法是最简单和代码最简洁的,但是可以发现的是,我们每次需要进行字符的切片操作,但是实际上只需要记录一下每次递归需要的字符索引即可。这样就写出了第二个版本的代码:

class Solution:
    def longestDecomposition(self, text: str) -> int:
        n = len(text)
        def dfs(l, r):
            if l > r: return 0
            # ans = 1
            for i in range(1, r - l + 1):
                if text[l:l + i] != text[r - i + 1:r + 1]:continue
                return 2 + dfs(l + i, r - i)
            return 1
        return dfs(0, n - 1)

此外,可以发现的是,因为匹配总是左右对称的,因此递归的时候确定了左边界,那么右边界也是直接可以确定的。据此也可以将递归的参数再减少一个。

其中最简单的办法就是在dfs的内部首先计算一下r,然后其余代码均不需要变动,这里就不在赘述。
这列给出一个不写出确定的右边界,而是通过左边界的最大值进行计算的代码

class Solution:
    def longestDecomposition(self, text: str) -> int:
        N = len(text)
        n,f = divmod(N,2)
        def dfs(l):
            if l>=n+f: return 0
            for i in range(1,n-l+1):
                if text[l:l+i] != text[N-i-l:N-l]:continue
                return 2 + dfs(l+i)
            return 1
        return dfs(0)
posted @ 2024-08-29 14:28  TICSMC  阅读(8)  评论(0)    收藏  举报