【问题标题】:Count double palindromes in given int sequence计算给定 int 序列中的双回文数
【发布时间】:2010-06-09 20:11:17
【问题描述】:

对于给定的 int 序列检查双回文数,其中双回文是指两个相同回文的序列,它们之间没有中断。比如:

在 1 0 1 1 0 1 中,我们有 1 0 1 作为回文,它连续出现 2 次,

在 1 0 1 5 1 0 1 我们有 1 0 1 但它是分开的

(除了这些序列中的其他回文)

问题示例测试数据为:

3

12 0 1 1 0 0 1 1 0 0 1 1 0

12 1 0 1 0 1 0 1 0 1 0 1 0

6 3 3 3 3 3 3

有答案

8 0 9

Manacher 对于乞讨是显而易见的,但我不确定下一步该做什么。任何想法表示赞赏。我猜复杂度应该低于 n^2。

编辑:int 在这里被视为字母表的单个元素

【问题讨论】:

  • 这是作业吗?这似乎不是一个具有实际相关性的问题......
  • 您是在寻找所有回文还是最长的回文?您的示例包含回文 1100 作为其他人的子回文。他们应该被识别,还是不被识别? (我假设要求是length(palindrome)>1)。
  • 是的,答案是所有回文数,单个部分的长度可能为 1,从示例测试数据中可以看出。 @Mark - 你可以这样称呼它。它没有实际意义……它是大学常用算法科目的一部分。
  • @jakubmal:你的教授讨论过寻找所有回文的算法吗?如果我们将这些回文限制为均匀长度会怎样?
  • @Moron:我的意思是 Manacher 是查找所有回文的算法(并且已经提出)。我通过在从 io 读取时在每个元素之间插入 -1 来消除偶数/奇数回文问题。实际上我在读高中,但我们有一种 AP 课程。

标签: algorithm palindrome


【解决方案1】:

由于您已经知道查找所有回文的算法(顺便说一句,这非常棒),您需要做的就是以下内容。请注意,“双回文”也是回文:
反向(PP)=反向(P)反向(P)=PP。

所以在你找到的所有回文(a,b)中((a,b)我的意思是从位置a到位置b的回文),你需要找到(i,j,k)这样(i,j)(j,k)(i,k) 都是回文,j-i=k-j。等效地,对于你找到的每个回文(i,j),你只需要设置k = 2j-i,并检查(k,j)(i,k)是否都是回文。

如果第一步总共返回 M 个回文,这需要 O(M) 时间(假设您存储它们以便检查是否存在回文是 O(1)),所以 O(n2) 在最坏的情况下。我相信这在最坏的情况下应该是最优的(考虑一串全为 1 的字符串)。

【讨论】:

  • 基本上就是这样。我们可以通过应用一些巧妙的算法来计算双回文数来进一步降低复杂度。它与 Manacher 非常相似,因为它只检查当前最大回文并自动将较小的回文附加到区间 (??) 树。
【解决方案2】:

我会从 2 个集合开始:

  • “生长”序列的集合
  • “收缩”序列的集合

算法是这样工作的:

  • 最初两个集合都是空的
  • 一一处理向量的值,假设我们现在正在查看值 V
  • 循环遍历所有“增长”序列
    • 如果增长序列的最后一个值等于 V,则将增长序列复制到收缩序列集合中,从新收缩序列的末尾删除 V
    • 如果增长序列的最后一个值等于 V,则将增长序列复制到收缩序列集合中,从收缩序列中删除最后 2 个元素(V 和最后一个)
  • 循环遍历所有“收缩”序列
    • 如果收缩序列的最后一个值等于 V,则将其从收缩序列中删除。如果一个收缩序列变为空,我们就找到了一个回文。
    • 如果收缩序列的最后一个值不等于V,则删除这个收缩序列
  • 最后制作一个只包含V的新生长序列

事实上,增长的序列是可能曾经成为回文的序列,而收缩的序列是“部分”回文。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多