当前位置: 首页 > news >正文

Leetcode 3504. Longest Palindrome After Substring Concatenation II

  • Leetcode 3504. Longest Palindrome After Substring Concatenation II
    • 1. 解题思路
    • 2. 代码实现
  • 题目链接:3504. Longest Palindrome After Substring Concatenation II

1. 解题思路

这一题是题目3503. Longest Palindrome After Substring Concatenation I的复杂版本,但其实也就是增加了算法复杂度的要求,本质上两题就是同一道题目。

这一题的题意核心其实就是从两个字符串st当中分别取两个可以为空的子串s't'使得两者合并为一个回文数组,然后求其最大长度。

显然,其结果可能包含两种情况:

  1. 最长的回文子串来自于单一字符串s或者t
  2. 最长的回文子串来自于两字符串s或者t的子串的合并结果

其中,对于第一个问题,其本质就是求给定任意一个字符串,求其中的最长回文子串。做法上来说我们就是构造一个反向字符串的字典树,然后依次考察其正向的字符串在其中的最大公共前缀子串是否为一个回文字符串。

然后,对于第二个问题,我们同样就是从s的正向和t找寻一个最大的公共前序子串,那么两者直接拼凑就一定回文字符串,而要令其最长,我们还可以进一步拼凑其后方的最大回文字符串。

其中,对于前者,我们同样可以通过字典树进行处理,对于后者,事实上我们就是要求一个问题:

  • 对于一个给定的字符串s,问其从头部开始能够找到的最长回文子串的长度是多少。

这个我们可以通过使用z算法进行处理。

而对于字典树和z算法,网上已经有很多相关教程了,我自己也写过两篇博客(《经典算法:Trie树结构简介》,《经典算法:Z算法(z algorithm)》)作为备忘了,因此这里就不过多展开了,有兴趣的读者可以自行了解一下。

2. 代码实现

给出python代码实现如下:

class Trie:
    def __init__(self):
        self.trie = {}
    
    def add_word(self, word):
        trie = self.trie
        for c in word:
            trie = trie.setdefault(c, {})
        trie["eos"] = ""

    def find(self, word):
        trie = self.trie
        for c in word:
            if c not in trie:
                return False
            trie = trie[c]
        return "eos" in trie
    
    def find_longest_prefix(self, word):
        prefix = ""
        trie = self.trie
        for c in word:
            if c not in trie:
                break
            prefix += c
            trie = trie[c]
        return prefix

def z_algorithm(s):
    n = len(s)
    z = [0 for _ in range(n)]
    l, r = -1, -1
    for i in range(1, n):
        if i > r:
            l, r = i, i
            while r < n and s[r-l] == s[r]:
                r += 1
            z[i] = r-l
            r -= 1
        else:
            k = i - l
            if z[k] < r - i + 1:
                z[i] = z[k]
            else:
                l = i
                while r < n and s[r-l] == s[r]:
                    r += 1
                z[i] = r-l
                r -= 1
    z[0] = n
    return z

class Solution:
    def longestPalindrome(self, s: str, t: str) -> int:
        n, m = len(s), len(t)
        ans = 0
        
        rs = s[::-1]
        trie_s = Trie()
        trie_rs = Trie()
        for i in range(n):
            trie_s.add_word(s[i:])
            trie_rs.add_word(rs[i:])
        for i in range(n):
            prefix = trie_s.find_longest_prefix(rs[i:])
            if prefix == prefix[::-1]:
                ans = max(ans, len(prefix))
        
        rt = t[::-1]
        trie_t = Trie()
        trie_rt = Trie()
        for i in range(m):
            trie_t.add_word(t[i:])
            trie_rt.add_word(rt[i:])
        for i in range(m):
            prefix = trie_t.find_longest_prefix(t[i:])
            if prefix == prefix[::-1]:
                ans = max(ans, len(prefix))
                
        for i in range(n):
            prefix = trie_rt.find_longest_prefix(s[i:])
            if i+len(prefix) == n:
                ans = max(ans, len(prefix) * 2)
            else:
                remain = s[i+len(prefix):]
                k = len(remain)
                z = z_algorithm(remain + remain[::-1])
                for j in range(k):
                    if z[k+j] == k-j:
                        ans = max(ans, len(prefix) * 2 + k-j)
                        
        for i in range(m):
            prefix = trie_s.find_longest_prefix(rt[i:])
            if i+len(prefix) == m:
                ans = max(ans, len(prefix) * 2)
            else:
                remain = rt[i+len(prefix):]
                k = len(remain)
                z = z_algorithm(remain + remain[::-1])
                for j in range(k):
                    if z[k+j] == k-j:
                        ans = max(ans, len(prefix) * 2 + k-j)
        return ans

提交代码评测得到:耗时6479ms,占用内存331.4MB。

相关文章:

  • react+antd封装一个可回车自定义option的select并且与某些内容相互禁用
  • ffmpeg中格式转换需要注意点总结
  • 设计模式基础入门
  • Android 使用CameraX实现预览、拍照、录制视频(Java版)
  • AI产品的基础设施:算法、数据与大语言模型
  • 解决安卓手机WebView无法直接预览PDF的问题(使用PDF.js方案)
  • 基于SpringBoot的仓库管理系统-023
  • 递归详解:从原理到实战
  • 9.常用模板引擎
  • Elasticsearch索引的字段映射
  • 串口中断接收与环形缓冲实例(apollo3 blue plus)
  • Perl 哈希
  • Springboot实战:如何用Docker和Kubernetes部署微服务
  • Unity中MonoBehaviour组件禁用时协程的行为
  • Qt基本框架(1)
  • 正则表达式和通配符
  • Python 中的 `partial`:函数参数预设的艺术
  • unity UI管理器
  • 笔记:代码随想录算法训练营day64:拓扑排序精讲、dijkstra(朴素版)精讲
  • 算法设计学习3
  • 上海:以税务支持鼓励探索更多的创新,助力企业出海
  • 看见“看得见的手”,看见住房与土地——读《央地之间》
  • 中国人保一季度业绩“分化”:财险净利增超92%,寿险增收不增利
  • 中国人保不再设监事会,国寿集团未再设置监事长职务
  • 复星医药换帅:陈玉卿接棒吴以芳任董事长,吴以芳改任复星国际执行总裁
  • 深入贯彻中央八项规定精神学习教育中央指导组派驻地方和单位名单公布