还原原始字符串 | 豆包MarsCode AI刷题

34 阅读3分钟

问题描述

给定一个字符串 FF,这个字符串是通过对某个初始字符串 SS 执行若干次以下操作得到的:

  • 选择一个整数 KK(其中 0≤K<∣S∣0≤K<∣S∣,∣S∣∣S∣ 表示字符串 SS 的长度)
  • 将 SS 从第 KK 个位置(从0开始计数)到末尾的子串追加到 SS 的末尾,即:S=S+S[K:]S=S+S[K:]

输入格式

  • 输入为一个字符串 FF,仅包含小写字母,长度不超过 1000。

输出格式

  • 输出一个字符串,表示可能的最短初始字符串 SS。
  • 如果无法通过题目描述的操作得到字符串 FF,则输出原字符串 FF。

测试样例

样例1:

输入:str1 = "abbabbbabb"
输出:"ab"

解释:初始字符串 "ab" 可以通过以下步骤得到最终字符串:

  1. K=1K=1:"a[b]""a[b][b]"
  2. K=0K=0:"[abb]""[abb][abb]"
  3. K=2K=2:"ab[babb]""ab[babb][babb]"

样例2:

输入:str1 = "abbbabbbb"
输出:"ab"

解释:初始字符串 "ab" 可以通过以下步骤得到最终字符串:
"a[b]""a[b][b]"
"ab[b]""ab[b][b]"
"[abbb]""[abbb][abbb]"
"abbbabb[b]""abbbabb[b][b]"

样例3:

输入:str1 = "jiabanbananananiabanbananananbananananiabanbananananbananananbananananbanananan"
输出:'jiaban'

样例4:

输入:str1 = "selectecttectelectecttectcttectselectecttectelectecttectcttectectelectecttectcttectectcttectectcttectectcttect"
输出:'select'

样例5:

输入:str1 = "discussssscussssiscussssscussssdiscussssscussssiscussssscussssiscussssscussss"
输出:'discus'

样例6:

输入:str1 = "lflsdjlskjflskjfl"
输出:'lflsdjlskjfl'

提示

  1. 考虑如何判断一个字符串是否可以通过题目描述的操作得到
  2. 可以尝试从短到长枚举可能的初始字符串
  3. 时间复杂度应不超过 O(n2)O(n2),其中 nn 为输入字符串的长度

我们可以先从短到长枚举所有可能的初始字符串,如abbabbbabb的话,可能的初始字符串为a,ab,abb,abba等等。再通过题目的操作,将初始字符串加长至所比对的字符串长度,如果相同的话,则满足条件直接返回,否则继续加长初始字符串直到为其本身。

核心算法实现过程:

  • 枚举初始字符串:使用一个从 1 到 <font style="color:rgb(26, 32, 41);">target.length()</font> 的循环来枚举可能的初始字符串长度。
  • 检查生成过程
    • 初始化 <font style="color:rgb(26, 32, 41);">current</font> 为当前的 <font style="color:rgb(26, 32, 41);">candidate</font>
    • 使用一个 <font style="color:rgb(26, 32, 41);">while</font> 循环,只要 <font style="color:rgb(26, 32, 41);">current</font> 的长度小于 <font style="color:rgb(26, 32, 41);">target</font> 的长度,就继续执行以下步骤:
      • 使用一个 <font style="color:rgb(26, 32, 41);">for</font> 循环来枚举所有可能的 <font style="color:rgb(26, 32, 41);">K</font> 值。
      • 对于每个 <font style="color:rgb(26, 32, 41);">K</font>,生成新的字符串 <font style="color:rgb(26, 32, 41);">newStr</font>,即 <font style="color:rgb(26, 32, 41);">current + current.substring(K)</font>
      • 检查 <font style="color:rgb(26, 32, 41);">newStr</font> 是否等于 <font style="color:rgb(26, 32, 41);">target</font>,如果是,则返回 <font style="color:rgb(26, 32, 41);">true</font>
      • 检查 <font style="color:rgb(26, 32, 41);">newStr</font> 是否是 <font style="color:rgb(26, 32, 41);">target</font> 的前缀,如果是,则更新 <font style="color:rgb(26, 32, 41);">current</font><font style="color:rgb(26, 32, 41);">newStr</font> 并退出 <font style="color:rgb(26, 32, 41);">for</font> 循环。
      • 如果 <font style="color:rgb(26, 32, 41);">for</font> 循环结束后没有找到合适的 <font style="color:rgb(26, 32, 41);">K</font>,则返回 <font style="color:rgb(26, 32, 41);">false</font>
  • 返回结果:如果 <font style="color:rgb(26, 32, 41);">current</font> 的长度等于 <font style="color:rgb(26, 32, 41);">target</font> 的长度且它们相等,则返回 <font style="color:rgb(26, 32, 41);">true</font>,否则返回 <font style="color:rgb(26, 32, 41);">false</font>
public class Main {
    public static String solution(String str1) {
        // 从短到长枚举可能的初始字符串 candidate
        for (int i = 1; i <= str1.length(); i++) {
            String candidate = str1.substring(0, i);
            // 检查 candidate 是否可以通过题目描述的操作生成 str1
            if (canGenerate(candidate, str1)) {
                return candidate;
            }
        }
        // 如果找不到满足条件的 candidate,返回原字符串
        return str1;
    }

    // 检查 candidate 是否可以通过题目描述的操作生成 target
    private static boolean canGenerate(String candidate, String target) {
        String current = candidate;
        // 不断追加子串,直到 current 的长度大于等于 target 的长度
        while (current.length() < target.length()) {
            boolean found = false;
            // 选择一个 K,追加子串
            for (int K = 0; K < current.length(); K++) {
                String newStr = current + current.substring(K);
                if (newStr.equals(target)) {
                    return true;
                }
                if (target.startsWith(newStr)) {
                    current = newStr;
                    found = true;
                    break;
                }
            }
            if (!found) {
                return false;
            }
        }
        // 如果 current 的长度等于 target 的长度,检查是否相等
        return current.equals(target);
    }

    public static void main(String[] args) {
        // Add your test cases here
        System.out.println(solution("abbabbbabb").equals("ab"));
        System.out.println(solution("abbbabbbb").equals("ab"));
        System.out.println(solution("jiabanbananananiabanbananananbananananiabanbananananbananananbananananbanananan")
                .equals("jiaban"));
        System.out.println(solution(
                "selectecttectelectecttectcttectselectecttectelectecttectcttectectelectecttectcttectectcttectectcttectectcttect")
                .equals("select"));
        System.out.println(solution("discussssscussssiscussssscussssdiscussssscussssiscussssscussssiscussssscussss")
                .equals("discus"));
    }
}