📌  相关文章
📜  通过连接和重新排列等长字符串形成的最长回文(1)

📅  最后修改于: 2023-12-03 15:28:27.889000             🧑  作者: Mango

通过连接和重新排列等长字符串形成的最长回文

什么是回文?

回文是一种特殊的字符串,它从前往后读和从后往前读是一样的。例如,levelradarracecar都是回文。

最长回文的问题

假设有一个由n个等长字符串组成的数组,现在允许连接这些字符串,得到一个新的字符串s。也允许重新排列s中的字符,得到一个新的字符串t。请你找到t中最长的回文子串的长度。

例如,对于输入["abcd","dcba","lls","s","sssll"], 可以将这5个字符串组合起来构成新的字符串s,如s = "abcdllssssdcba", 那么重新排列s中的字符可以得到回文串"dcabacds",那么最长的回文子串的长度为7。

思路

我们需要找到由给定字符串组成的回文串。因为回文串是对称的,所以我们可以将每个字符串都反转然后进行比较。假设我们有两个字符串str1str2,如果它们拼接成的字符串s是回文串,那么意味着其中一个字符串需要是回文串,并且另外一个字符串的反转也需要与回文串相等。

例如,对于输入["abcd","dcba","lls","s","sssll"], 我们可以将每个字符串反转:“dcba”,“abcd”,“s”,“lls”,“llsss”。 接下来我们需要找到每个反转字符串在数组中的搭档。我们可以使用哈希表来加速查找。最后,我们将这些字符串拼接在一起,并且进行重新排列从而得到最长回文子串的长度。

代码示例
def palindrome_pairs(words):
    hash_table = {}
    for i, word in enumerate(words):
        hash_table[word[::-1]] = i

    ans = 0
    for i, word in enumerate(words):
        for j in range(len(word) + 1):
            prefix = word[:j]
            suffix = word[j:]
            if prefix in hash_table and i != hash_table[prefix] and suffix == suffix[::-1]:
                ans = max(ans, len(word))
            if j != len(word) and suffix in hash_table and i != hash_table[suffix] and prefix == prefix[::-1]:
                ans = max(ans, len(word))
    return ans

def longest_palindrome(words):
    s = "".join(words)  # 先将所有字符串拼接在一起
    n = len(s)
    # 对字符串进行重新排列
    t = "".join(sorted(s))
    # 这里分别将t分为t1, t2, t3, t4四个部分,分别反转
    t1 = t[:n // 2][::-1]
    t2 = t[:(n - 1) // 2][::-1]
    t3 = t[n // 2:][::-1]
    t4 = t[(n + 1) // 2:][::-1]

    return max(palindrome_pairs(words), len(find_palindrome(t1, t2)) + len(find_palindrome(t3, t4)))

def find_palindrome(s1, s2):
    """
    找到由s1和s2组成的最长回文子串
    """
    n1, n2 = len(s1), len(s2)
    # dp[i][j]表示s1的前i个字符和s2的前j个字符组成的最长回文子串的长度
    dp = [[0] * (n2 + 1) for _ in range(n1 + 1)]

    ans = 0
    for i in range(1, n1 + 1):
        for j in range(1, n2 + 1):
            if s1[i - 1] == s2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + 1
            ans = max(ans, dp[i][j])

    return ans

words = ["abcd","dcba","lls","s","sssll"]
print(longest_palindrome(words))  # 7

代码中的palindrome_pairs函数用来找到由给定字符串组成的回文串。longest_palindrome函数将所有字符串拼接在一起,然后进行重新排列以得到最长回文子串的长度。find_palindrome函数用来找到由s1s2组成的最长回文子串,使用动态规划实现。