当前位置: 首页 > news >正文

43还原原始字符串-Java版-青训营刷题

问题描述

给定一个字符串 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 为输入字符串的长度

代码如下

public class Main {
 
    public static String solution(String str1) {
        //直接正向思考测试是否能进行转换
 
        //特殊情况
        if(str1.equals("")) return "";
        String s = "" + str1.charAt(0);
        if(s.repeat(str1.length()).equals(str1)) return s;
 
        //进行遍历判断
        for(int i = 2; i <= str1.length();i++){
            String str = str1.substring(0,i);
            if(get(str,str1)){
                return str;
            }
        }
        return "ab";
    }
 
    public static boolean get(String str, String target) {
        //核心实现
        // 进行一个递归出口判断
        if (!target.startsWith(str)) {
            return false;
        } else {
            if (str.length() == target.length()) {
                return true;
            }
        }
 
        // 进行一个判断
        for (int i = 0; i < str.length(); i++) {
            int count = str.length();
            if (str.length() < target.length())//防止进入死循环
                str = str + str.substring(i);
            if (get(str, target)) {
                return true;
            } else {
                // 当前的添加不正确,进行回溯寻找下一个路径
                str = str.substring(0,count);
            }
        }
        return false;
    }
 
 
    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"));
    }
}

代码解释

这段代码的目标是找到一个字符串的最短“生成子串”,使得通过某种方式重复和拼接这个子串可以生成原始字符串。如果无法找到这样的子串,则返回 "ab"。以下是对代码的详细解释:


代码功能概述

  1. solution 方法

    • 输入一个字符串 str1

    • 尝试找到一个最短的子串,使得通过某种方式重复和拼接这个子串可以生成原始字符串。

    • 如果找到这样的子串,返回它;否则返回 "ab"

  2. get 方法

    • 这是一个递归方法,用于判断一个子串是否可以通过某种方式扩展成目标字符串。

    • 它通过尝试在子串的末尾添加子串的某个部分,并递归检查是否能生成目标字符串。


代码详细解释

1. solution 方法

java复制

public static String solution(String str1) {
    // 特殊情况:空字符串直接返回空
    if (str1.equals("")) return "";

    // 检查是否可以通过单个字符重复生成整个字符串
    String s = "" + str1.charAt(0);
    if (s.repeat(str1.length()).equals(str1)) return s;

    // 遍历所有可能的子串长度
    for (int i = 2; i <= str1.length(); i++) {
        String str = str1.substring(0, i);
        if (get(str, str1)) { // 如果当前子串可以生成目标字符串
            return str;
        }
    }
    return "ab"; // 如果没有找到合适的子串,返回 "ab"
}

关键逻辑:

  1. 特殊情况处理

    • 如果输入字符串为空,直接返回空字符串。

    • 如果输入字符串可以通过单个字符重复生成(例如 "aaaa"),返回该字符。

  2. 遍历所有可能的子串

    • 从长度为 2 开始,尝试所有可能的子串(str1.substring(0, i))。

    • 使用 get 方法检查当前子串是否可以通过某种方式扩展成目标字符串。

    • 如果找到合适的子串,立即返回。

2. get 方法

java复制

public static boolean get(String str, String target) {
    // 如果目标字符串不以当前子串开头,直接返回 false
    if (!target.startsWith(str)) {
        return false;
    } else {
        // 如果当前子串长度等于目标字符串长度,说明已经匹配成功
        if (str.length() == target.length()) {
            return true;
        }
    }

    // 尝试在子串末尾添加子串的某个部分
    for (int i = 0; i < str.length(); i++) {
        int count = str.length();
        if (str.length() < target.length()) { // 防止进入死循环
            str = str + str.substring(i);
        }
        if (get(str, target)) { // 递归检查
            return true;
        } else {
            // 当前添加不成功,回溯到之前的子串
            str = str.substring(0, count);
        }
    }
    return false; // 如果所有尝试都失败,返回 false
}

关键逻辑:

  1. 递归出口

    • 如果目标字符串不以当前子串开头,直接返回 false

    • 如果当前子串长度等于目标字符串长度,且匹配成功,返回 true

  2. 尝试扩展子串

    • 遍历子串的每个字符,尝试在子串末尾添加子串的某个部分(str.substring(i))。

    • 递归调用 get 方法,检查新的子串是否可以生成目标字符串。

    • 如果递归返回 true,说明找到了一种可行的扩展方式,返回 true

    • 如果当前扩展方式失败,回溯到之前的子串状态,尝试下一种扩展方式。

  3. 防止死循环

    • 在尝试扩展子串时,通过 if (str.length() < target.length()) 确保不会无限制地扩展。


测试用例

java复制

public static void main(String[] args) {
    System.out.println(solution("abbabbbabb").equals("ab")); // 输出 true
    System.out.println(solution("abbbabbbb").equals("ab")); // 输出 true
    System.out.println(solution("jiabanbananananiabanbananananbananananiabanbananananbananananbanananan").equals("jiaban")); // 输出 true
    System.out.println(solution("selectecttectelectecttectcttectselectecttectelectecttectcttectectelectecttectcttectectcttectectcttect").equals("select")); // 输出 true
    System.out.println(solution("discussssscussssiscussssscussssdiscussssscussssiscussssscussssiscussssscussss").equals("discus")); // 输出 true
}

测试用例解释:

  1. 对于 "abbabbbabb",最短生成子串是 "ab"

  2. 对于 "abbbabbbb",最短生成子串也是 "ab"

  3. 对于长字符串,代码尝试找到一个最短的子串,使得通过某种方式重复和拼接可以生成原始字符串。


代码的逻辑问题

虽然代码的逻辑看起来合理,但实际上存在一些问题:

  1. 效率问题

    • get 方法的递归实现可能导致大量重复计算,效率较低。

    • 对于较长的字符串,可能会超时。

  2. 逻辑问题

    • get 方法的实现中,尝试通过扩展子串来匹配目标字符串,但这种方式可能无法覆盖所有情况。

    • 例如,对于 "abababab",代码可能无法找到正确的生成子串 "abab"

  3. 返回 "ab" 的问题

    • 如果没有找到合适的子串,代码返回 "ab",这可能不是最佳选择。


改进建议

  1. 优化递归逻辑

    • 使用动态规划或记忆化递归来避免重复计算。

  2. 改进生成子串的判断逻辑

    • 可以尝试通过数学方法或更高效的字符串匹配算法来判断生成子串。

  3. 改进返回值

    • 如果没有找到合适的子串,返回 null 或抛出异常,而不是返回 "ab"


 

 

相关文章:

  • 文心快码|AI重构开发新范式,从工具到人机协同
  • 高效高并发调度架构
  • UE5.3 C++ USTRUCT的规范使用和制作简单的画线插件
  • 万字长文破解 AI 图片生成算法-Stable diffusion
  • flutter hive使用(复杂类)
  • 如何在Flask中处理静态文件
  • DeepSeek生成思维导图
  • cxxopts位置参数示例
  • SEO短视频矩阵系统源码开发概述
  • 一维差分算法篇:高效处理区间加减
  • 三维重建(十二)——3D先验的使用
  • VisoMaster整合包及汉化
  • 如何用 Linux 权限管理打造无懈可击的系统?
  • Python编程笔记
  • 微软AutoGen高级功能——Selector Group Chat
  • pt->onnx->rknn(量化) step by step FAQ
  • Linux vmstat 命令
  • 【自学笔记】机器学习基础知识点总览-持续更新
  • Spring Data Neo4j
  • DeepSeek+Excel 效率翻倍
  • 百度云域名怎么做网站/西安自动seo
  • 做二手车有哪些网站有哪些手续/泉州百度搜索推广
  • ftp 修改网站/成都官网seo厂家
  • 宣传京津风筝网站的建设目的/新产品如何快速推广市场
  • 公共体育课程网站建设/怎么自己做网站推广
  • 电商怎么做营销推广w/什么叫优化