459. Repeated Substring Pattern

本文介绍了一种算法,用于判断一个给定的非空字符串是否可以通过重复其内部的一个子字符串来构造。通过逐步分析并提供代码实现,展示了如何验证这一条件。

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

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

Example 1:

Input: "abab"

Output: True

Explanation: It's thesubstring "ab" twice.


Example 2:

Input: "aba"

Output: False

Example 3:

Input:"abcabcabcabc"

Output: True

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

    翻译:给定一个非空字符串检查,如果它可以通过取其子字符串并将子字符串的多个副本附加在一起构造。您可以假定给定字符串仅由小写英文字母组成,其长度不超过10000

    分析:直接假设他重复的次数,然后将它的子串和原串比较,若找到一个重复的次数,则返回ture.可能时间复杂度比较高,代码如下:

public class Solution {

    public boolean test(String s,int length){

           //比较他们的是否是重复的

           int count=s.length()/length;

           for(int i=0;i<s.length();i++){

                 if(s.charAt(i)!=s.charAt(i%count)) return false;//直接到了固定的数,循环回来比较

           }

           return true;

    }

    public booleanrepeatedSubstringPattern(String s) {

           int len=s.length();

           if(len==1) return false;

           //假设字符串循环2len

           boolean flag=false;

           for(int i=2;i<=len&&!flag;i++){

                 if(len%i!=0) continue;

                 flag=test(s,i);

           }

           return flag;

    }

}

### 错误分析 在给定的 `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、付费专栏及课程。

余额充值