AI刷题中档题 还原原始字符串 解答 | 豆包MarsCode AI刷题

33 阅读4分钟

还原原始字符串

问题描述

给定一个字符串 F,它是通过某个初始字符串 S 执行若干次操作得到的。操作规则如下:

  1. 选择一个整数 K,满足 0≤K<∣S∣(其中∣S∣ 表示 S 的长度)。
  2. 将 S 的第 K 个位置到末尾的子串追加到 S 的末尾,即: S=S+S[K:] 根据上述规则,字符串 FFF 是通过对初始字符串 SSS 的重复拼接生成的。

目标: 根据给定的字符串 F,找出可能的最短初始字符串 S。如果无法通过上述操作得到 F,则直接输出 F 本身。


问题分析

我们需要从字符串 F 中反推出生成它的最短初始字符串 S。仔细观察可以发现,生成字符串的操作使 F 具有某种周期性模式。例如,字符串 "abbabbbabb" 是由 "ab" 通过多次拼接生成的,而不是 "abb" 或更长的前缀。
这启发我们将问题归结为寻找字符串 F 的最短周期,即字符串中最短的重复模式。

进一步分析发现:

  1. F 的最短周期决定了 S 的长度。
  2. 如果 F 中存在某个重复子串,且此子串可以通过题目规则生成整个 F,那么该子串就是初始字符串 S。
  3. 如果 F 不具有上述性质,则 S=F。

解决该问题的关键在于高效地找到 F 的重复模式并验证其合法性。


解题思路

可以通过递归搜索和字符串匹配来解决该问题:

  1. 从末尾向前递归搜索
    对于字符串 F,假设当前考虑位置为 rear。
    从 rear向前尝试寻找一个子串 S[i:rear+1],验证它是否是重复的。如果发现某个子串符合条件,就缩短 rear 并继续递归。
  2. 字符串匹配判断
    检查 S[i:rear+1] 是否满足条件的关键是验证该子串是否可以生成从 i 到 rear+1 的部分。
    如果满足,则递归向前寻找更短的 S。
  3. 结果比较
    在每次递归中维护一个当前最优解,即找到的最短 S。
  4. 边界条件
    如果无法找到任何重复模式,则直接返回 F 自身。

算法实现

以下是 Python 实现

def dfs(s,rear):
    result = s[:rear+1]
    for i in range(rear,rear//2,-1):
        if s[i:rear+1] == s[i-(rear+1-i):i]:
            res = dfs(s,i-1)
            if len(result) > len(res):
                result = res
    return result

def solution(str1):
    # Edit your code here
    return dfs(str1,len(str1)-1)


if __name__ == "__main__":
    # Add your test cases here

    print(solution("abbabbbabb"))
    print(solution("abbbabbbb") == "ab")
    print(
        solution(
            "jiabanbananananiabanbananananbananananiabanbananananbananananbananananbanananan"
        )
        == "jiaban"
    )
    print(
        solution(
            "selectecttectelectecttectcttectselectecttectelectecttectcttectectelectecttectcttectectcttectectcttectectcttect"
        )
        == "select"
    )
    print(
        solution(
            "discussssscussssiscussssscussssdiscussssscussssiscussssscussssiscussssscussss"
        )
        == "discus"
    )
    

示例解析

以下是几个测试样例的详细分析:

样例1:
输入:"abbabbbabb"

  • 初始字符串为 "ab"

  • 执行步骤:

    • K=1K = 1K=1:"a[b]" → "a[b][b]"
    • K=0K = 0K=0:"[abb]" → "[abb][abb]"
    • K=2K = 2K=2:"ab[babb]" → "ab[babb][babb]"
      输出:"ab"

样例2:
输入:"abbbabbbb"

  • 初始字符串为 "ab"

  • 执行步骤:

    • K=1K = 1K=1:"a[b]" → "a[b][b]"
    • K=0K = 0K=0:"[abbb]" → "[abbb][abbb]"
      输出:"ab"

样例3:
输入:"jiabanbananananiabanbananananbananananiabanbananananbananananbananananbanananan"

  • 初始字符串为 "jiaban"
  • 经过多次重复生成,最终得到字符串。
    输出:"jiaban"

复杂度分析

  1. 时间复杂度:

    • 每次递归最多检查当前字符串的一半长度,整体复杂度为 O(n2),其中 n 是字符串的长度。
  2. 空间复杂度:

    • 递归调用的栈深度最多为 O(n),但没有额外的数据结构,整体空间复杂度为 O(n)。

总结

该问题的核心在于识别字符串的重复模式。算法通过递归和匹配结合,逐步缩小搜索范围,寻找可能的最短初始字符串 S。对于特殊情况下无法生成 F 的情况,算法会返回原字符串,保证了结果的正确性和完整性。

这道题通过递归解决字符串生成问题,逻辑清晰,算法高效,是处理字符串周期性问题的一种典型方法