459. Repeated Substring Pattern(easy)

本文介绍了一种通过正则表达式和步进法检测字符串是否由重复子串构成的方法。利用正则表达式的match方法及步进法遍历检查,实现了高效地判断字符串是否由某一子串重复拼接而成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Easy

906105FavoriteShare

Given a non-empty string check if it can be constructed by taking a substring of it and appending multiple copies of the substring together. You may assume the given string consists of lowercase English letters only and its length will not exceed 10000.

 

Example 1:

Input: "abab"

Output: True

Explanation: It's the substring "ab" twice.

Example 2:

Input: "aba"

Output: False

Example 3:

Input: "abcabcabcabc"

Output: True

Explanation: It's the substring "abc" four times. (And the substring "abcabc" twice.)

 

使用正则表达式匹配:

Java:

/*
 * @Autor: SourDumplings
 * @Date: 2019-09-26 16:16:54
 * @Link: https://github.com/SourDumplings/
 * @Email: changzheng300@foxmail.com
 * @Description: https://leetcode.com/problems/repeated-substring-pattern/
 * 
 * 直接使用String的match方法利用正则表达式进行匹配每一个前缀子串,
 * 注意先判断前缀子串的长度是否是总长度的约数进行剪枝,否则会超时
 */

class Solution
{
    public boolean repeatedSubstringPattern(String s)
    {
        int l = s.length();
        for (int i = 1; i <= l / 2; i++)
        {
            if (l % i == 0 && s.matches("(" + s.substring(0, i) + ")+"))
            {
                return true;
            }
        }
        return false;
    }
}

 尝试步进法:

C++:

/*
 * @Autor: SourDumplings
 * @Date: 2019-09-26 16:07:37
 * @Link: https://github.com/SourDumplings/
 * @Email: changzheng300@foxmail.com
 * @Description: https://leetcode.com/problems/repeated-substring-pattern/
 * 
 * 思路就是尝试第一个子串和第二个之间的距离,看能否找到一个,时间复杂度为O(n^2)
 */

class Solution
{
public:
    bool repeatedSubstringPattern(string s)
    {
        int l = s.length();
        for (int d = 1; d < l; d++)
        {
            for (int i = 0; i < l - d; ++i)
            {
                if (s[i] != s[i + d])
                {
                    break;
                }
                if (l % d == 0 && i + d == l - 1)
                {
                    return true;
                }
            }
        }
        return false;
    }
};

 

### 错误分析 在给定的 `getnext` 函数实现中存在一些逻辑问题,这些问题可能导致程序行为不符合预期。 #### 1. 初始化问题 函数中的 `next[0] = -1;` 是合理的,因为这是 KMP 算法的一部分。然而,在后续处理过程中,当 `j == -1` 时,仍然会执行 `s[j+1] != s[i]` 的比较操作[^3]。这种情况下可能会导致未定义的行为,因为在某些编程环境中访问数组越界是不允许的操作。 #### 2. 更新条件不充分 另一个问题是更新 `j++` 和赋值 `next[i]=j` 的顺序以及判断条件不够严谨。具体来说: - 当前代码仅在 `if(s[j+1] == s[i])` 成立的情况下才增加 `j` 并设置 `next[i]`。 - 如果两个字符相等,则应该先让 `j++` 再将其作为新位置保存到 `next[i]` 中。 - 同样重要的是即使两者不同也应当考虑将当前索引设为 `-1` 或者其他适当初始值来表示没有匹配发生。 因此建议修改这部分逻辑如下所示: ```cpp while (j >= 0 && s[j + 1] != s[i]) { j = next[j]; } // 不论是否匹配都需要前进一位 j++; next[i] = j; ``` #### 3. 边界情况处理不当 最后一点是在计算周期性的判定表达式里有一个加号的位置错误: ```cpp len % (len - next[len - 1] + 1) == 0 ``` 这里实际上应该是减去而不是加上一,这样才能得到正确的子串长度用于检测是否存在重复模式。修正后的版本应改为: ```cpp len % (len - next[len - 1] - 1) == 0 ``` 通过以上调整可以提高此部分代码的健壮性和准确性。 ### 修改后的代码示例 以下是经过改进后的 C++ 实现方式: ```cpp vector<int> getnext(string s) { vector<int> next(s.size()); int j = -1; next[0] = -1; for (int i = 1; i < s.size(); ++i) { while (j >= 0 && s[j + 1] != s[i]) { j = next[j]; } j++; // 移动至下一状态 next[i] = j; // 额外优化:避免不必要的回溯 if (s[i] == s[next[i]]) next[i] = next[next[i]]; } return next; } bool repeatedSubstringPattern(const string& s) { if (s.empty()) return false; auto next = getnext(s); const size_t len = s.length(); // 正确地检查是否有重复模式 return next.back() != -1 && len % (len - next.back() - 1) == 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值