从单词列表中构造回文

Constructing palindrome from a list of words

本文关键字:回文 单词 列表      更新时间:2023-10-16

最近我在看一些面试问题,发现了一些有趣的问题:

给你一个单词列表。找出两个单词是否可以连接起来形成一个回文。考虑一个列表{bat, tab, cat},然后bat和tab可以连接起来形成一个回文。期望一个O(nk)的解决方案,其中n =作品数,k为长度

可以有多个对,如果找到就返回true。

另外,在评论中,其中一种方法是:

1)将第一个单词添加到树(A B)
2)取第二个单词(D E E D B A),倒写(A B D E E D)
3)看你能在字母表中匹配多少个倒过来的字母(前2个)
4)取字符串的其余部分(D E E D),看看它是否是回文,如果是,则返回true
5)将第二个单词添加到三(D E E D B A)
6)用下一个单词
返回步骤27)当缺字时返回false

但在我看来,这不是一个0 (nk)的解决方案。

谁能提出一个解决方案?或者解释一下为什么上面描述的算法是O(nk)??

算法是正确的,或者至少非常接近。有一些小的技术问题。在步骤4中。如果一个解决方案比当前方案更好,那么在步骤7中应该保存这个方案。返回它,或者说不可能生成回文

主要思想是将单词处理成核和前缀。如果核心是回文,那么我们需要用其他单词匹配前缀。Trie作为处理过的字符串的"数据库",因此对于每个新单词,可以检查所有可能的扩展。如果单词单独保存,则需要分别比较每个单词的前缀。

(编辑:我认为仍然存在一个小漏洞,以防在一个字符串中有两个开头相同的单词,而进入的单词将与较短的单词组成回文,而不是较长的单词,但我不会详细说明。处理它会使算法复杂化,但不会影响复杂度。)

也为O(n*k)。添加和检查前缀与trie所需的步数与字符数成正比。在这种情况下,它是由k束缚的。就像树的操作是O(h),其中h是树的高度。所以总结一下:

  1. k steps.

  2. 采取k步骤

  3. 也最多执行k步。

  4. 也比k的步骤少,但我们可以通过k来约束它。

  5. 也执行k步骤

步骤2至步骤5重复n-1次。

当然,每一步都有不同的主导操作,所以很难指定确切的常数,但它们都受k的约束,所以复杂度是O(c*(n-1)*k),本质上是O(n*k)

Dobbs博士在2004年的一篇文章中对此进行了非常有趣的讨论。完整的解释有点长,但大意是:

假设您从Lion开始,其中枢轴位于实际单词的左侧。我可以计算弦的中心,也就是位置2。枢轴是零,所以字符串在右边太重了,但目前,Lion符合部分回文的条件。轴心点上的"点"与轴心点上的点相匹配,因此至少有一个正确的字符,尽管是相同的字符。现在,您希望在以noil结尾的单词前添加前缀,并尝试将字符串转换为noil. lion。我指的是任何字符串。如果您成功了,那么您需要定位以开头的单词,以便将它们添加到字符串中。

注意,他将部分回文定义为:

如果从枢轴点向外工作,在不匹配发生之前遇到字符串的左端或右端,则字符串是部分回文。