给定一组唯一的单词, 找出所有不同 的索引对(i, j),使得列表中的两个单词, words[i] + words[j] ,可拼接成回文串。

示例 1:

输入: [“abcd”,“dcba”,“lls”,“s”,“sssll”]
输出: [[0,1],[1,0],[3,2],[2,4]]
解释: 可拼接成的回文串为 [“dcbaabcd”,“abcddcba”,“slls”,“llssssll”]

示例 2:

输入: [“bat”,“tab”,“cat”]
输出: [[0,1],[1,0]]
解释: 可拼接成的回文串为 [“battab”,“tabbat”]

暴力枚举

本题可以想到暴力做法,我们枚举每一对字符串的组合,暴力判断它们是否能够构成回文串即可。时间复杂度 O(n2×m),其中 n 是字符串的数量,m 是字符串的平均长度。时间复杂度并不理想,考虑进行优化。

Code

    def palindromePairs(self, words: List[str]) -> List[List[int]]:ans = []for i in range(len(words)):for j in range(len(words)):if i != j:temp = words[i] + words[j]if temp == temp[::-1]:ans.append([i, j])return ans

字典树/哈希表+前后缀

假设存在两个字符串 s1 和 s2,s1+s2 是一个回文串,记这两个字符串的长度分别为 len1 和 len2,我们分三种情况进行讨论:

  1. len1=len2,这种情况下 s1 是 s2 的翻转。
  2. len1>len2,这种情况下我们可以将 s1 拆成左右两部分:t1 和 t2,其中 t1 是 s2 的翻转,t2是一个回文串。
  3. len1<len2,这种情况下我们可以将 s2 拆成左右两部分:t1 和 t2,其中 t2 是 s1 的翻转,t1是一个回文串。

这样,对于每一个字符串,我们令其为 s1 和 s2 中较长的那一个,然后找到可能和它构成回文串的字符串即可。

具体地说,我们枚举每一个字符串 kkk,令其为 s1s_1s1​ 和 s2s_2s2​ 中较长的那一个,那么 kkk 可以被拆分为两部分,t1t_1t1​ 和 t2t_2t2​。

  1. 当 t1t_1t1​ 是回文串时,符合情况 333,我们只需要查询给定的字符串序列中是否包含 t2t_2t2​ 的翻转。
  2. 当 t2t_2t2​ 是回文串时,符合情况 222,我们只需要查询给定的字符串序列中是否包含 t1t_1t1​ 的翻转。

也就是说,我们要枚举字符串 kkk 的每一个前缀和后缀,判断其是否为回文串。如果是回文串,我们就查询其剩余部分的翻转是否在给定的字符串序列中出现即可。

注意到空串也是回文串,所以我们可以将 kkk 拆解为 k+∅k+\varnothingk+∅ 或 ∅+k\varnothing+k∅+k,这样我们就能将情况 111 也解释为特殊的情况 222 或情况 333。

而要实现这些操作,我们只需要设计一个能够在一系列字符串中查询「某个字符串的子串的翻转」是否存在的数据结构,有两种实现方法:

  • 我们可以使用字典树存储所有的字符串。在进行查询时,我们将待查询串的子串逆序地在字典树上进行遍历,即可判断其是否存在。

  • 我们可以使用哈希表存储所有字符串的翻转串。在进行查询时,我们判断带查询串的子串是否在哈希表中出现,就等价于判断了其翻转是否存在。

字典树 Code

class Node:def __init__(self):self.ch = [0] * 26self.flag = -1class Solution:def palindromePairs(self, words: List[str]) -> List[List[int]]:tree = [Node()]def insert(s: str, index: int):length = len(s)add = 0for i in range(length):x = ord(s[i]) - ord("a")if tree[add].ch[x] == 0:tree.append(Node())tree[add].ch[x] = len(tree) - 1add = tree[add].ch[x]tree[add].flag = indexdef findWord(s: str, left: int, right: int) -> int:add = 0for i in range(right, left - 1, -1):x = ord(s[i]) - ord("a")if tree[add].ch[x] == 0:return -1add = tree[add].ch[x]return tree[add].flagdef isPalindrome(s: str, left: int, right: int) -> bool:length = right - left + 1return length < 0 or all(s[left + i] == s[right - i] for i in range(length // 2))n = len(words)for i, word in enumerate(words):insert(word, i)ret = list()for i, word in enumerate(words):m = len(word)for j in range(m + 1):if isPalindrome(word, j, m - 1):leftId = findWord(word, 0, j - 1)if leftId != -1 and leftId != i:ret.append([i, leftId])if j and isPalindrome(word, 0, j - 1):rightId = findWord(word, j, m - 1)if rightId != -1 and rightId != i:ret.append([rightId, i])return ret

哈希表 Code

    def palindromePairs(self, words: List[str]) -> List[List[int]]:def findWord(s: str, left: int, right: int) -> int:return indices.get(s[left: right + 1], -1)def isPalindrome(s: str, left: int, right: int) -> bool:sub = s[left: right + 1]return sub == sub[::-1]n, ret = len(words), list()indices = {word[::-1]: i for i, word in enumerate(words)}for i, word in enumerate(words):m = len(word)for j in range(m + 1):if isPalindrome(word, j, m - 1):leftId = findWord(word, 0, j - 1)if leftId != -1 and leftId != i:ret.append([i, leftId])if j and isPalindrome(word, 0, j - 1):rightId = findWord(word, j, m - 1)if rightId != -1 and rightId != i:ret.append([rightId, i])return ret

336. Palindrome Pairs 回文对相关推荐

  1. 【To Understand!回文串8 哈希表】LeetCode 336. Palindrome Pairs

    LeetCode 336. Palindrome Pairs Solution1:我的答案 最笨的方法,果然因为时间复杂度太高而无法AC-- 难怪是hard 只是记录一下-- class Soluti ...

  2. C++palindrome partitioning回文分割算法的实现(附完整源码)

    C++palindrome partitioning回文分割算法的实现 C++palindrome partitioning回文分割算法的实现的完整源码(定义,实现,main函数测试) C++pali ...

  3. 动态规划 53:Maximum Subarray,152:Maximum Subarray,266. Palindrome Permutation 回文全排列...

    题意:寻找子数组的和最大. 思路:设置dp数组来保存到第i位的最大和. 判断第i-1位的正负,若dp[i-1]<0 则 dp[i] = nums[i]; 若 dp[i-1] > 0 则 d ...

  4. CodeForces - 932G Palindrome Partition(回文自动机+Palindrome Series优化dp)

    题目链接:点击查看 题目大意:给出一个长度为偶数的字符串,问将其分割成 k 个子串记为 a[ 1 ] , a[ 2 ] ... a[ k ] ,且满足 a[ i ] == a[ k - i + 1 ] ...

  5. 【CodeForces - 798A】Mike and palindrome (回文串,水题,字符串问题)

    题干: Mike has a string s consisting of only lowercase English letters. He wants to change exactly one ...

  6. 【LeetCode】Palindrome Number(回文数)

    这道题是LeetCode里的第9道题. 题目说的: 判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 示例 1: 输入: 121 输出: true 示例 2: ...

  7. 2019牛客暑期多校训练营(第六场)C - Palindrome Mouse (回文树dfs)

    题目链接 题意 一个字符串,求有多少对(S,T)(S,T)(S,T),满足S.TS.TS.T是回文串,S是T的子串S是T的子串S是T的子串 思路 题解还没看懂- 看大佬代码,好多在回文树上dfsdfs ...

  8. HDU - 6599 I Love Palindrome String (回文树+Manacher、回文树+hash)

    题目链接 题意 一个长度为3e5的字符串,求长度为iii的字符串满足字符是回文串而且字符串的前一半也是回文串的个数 思路 回文数求出所有的回文字符串,然后用Manacher或者Hash判断是否符合条件 ...

  9. POJ2402 Palindrome Numbers 回文数

    题目链接: http://poj.org/problem?id=2402 题目大意就是让你找到第n个回文数是什么. 第一个思路当然是一个一个地构造回文数直到找到第n个回文数为止(也许大部分人一开始都是 ...

最新文章

  1. nginx 反向代理,动静态请求分离,proxy_cache缓存及缓存清除
  2. Oracle KFED 和 KFOD 工具说明
  3. DM368开发 -- Bootloader 开发(转毕设)
  4. App正义联盟VS App Store、领英上线视频故事、亚马逊进军游戏流媒体| Decode the Week...
  5. android 网络连接 网络是否可用,Android 使用ping判断网络/WIFI连接是否可用
  6. 如何快速获取properties中的配置属性值
  7. 多线程环境下,HashMap为什么会出现死循环?
  8. OVS 网桥的Patch端口学习笔记
  9. MapReduce分布式编程框架
  10. [文艺节目/礼仪大赛策划方案]图:选手出场时?如何用Flash透明渲染PPT?展示排行榜时如何使用PPT及Flash渲染?
  11. idea导入项目后,没有项目结构
  12. 非编系统到底是什么意思呀?
  13. 圣笛数控联手国促会数外委打造OID物联新高地
  14. [数据可视化] 折线图(Line Chart)
  15. ZBrush 笔刷的基础参数
  16. 【总结】期望和方差以及为什么方差是要除以n-1
  17. 关于树叶的活动设计_大班游戏活动《有趣的叶子》教案
  18. WUST 五一萌新向CTF writup
  19. 05- 防火墙用户管理
  20. 对象存储OSS之ossbrowser的使用

热门文章

  1. nyoj13-Fibonacci数
  2. [老老实实学WCF] 第八篇 实例化
  3. 在sitecopy中设置不支持passive模式的ftp服务器
  4. 加速Javascript:DOM操作优化
  5. SqlHelper 数据库操作类
  6. oracle中的cursor属性有哪些,Cursor语法及理解
  7. linux文件的打包与下载总结,linux下文件的打包和压缩
  8. MutationObserver详解
  9. Python【每日一问】08
  10. BZOJ 3991: [SDOI2015]寻宝游戏