在给定的字符串中查找重复的子字符串模式

时间:2016-11-18 05:55:21

标签: regex string algorithm

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

示例1: 输入:" abab"

输出:True

说明:它是子串" ab"两次。 例2: 输入:" aba"

输出:错误 例3: 输入:" abcabcabcabc"

输出:True

说明:它是子串" abc"四次。 (和子串" abcabc"两次。)

我在在线编程网站here上找到了上述问题。我提交了以下答案,该答案适用于自定义测试用例,但在提交时时间超过了例外。我尝试了其他方式的正则表达式模式匹配,但正如预期的那样,这应该花费更多的时间,而且也失败了。

public class Solution {
    public boolean repeatedSubstringPattern(String str) {
        int substringEndIndex = -1;
        int i = 0;
        char startOfString = str.charAt(0);
        i++;
        char ch;
        while(i < str.length()){
            if((ch=str.charAt(i)) != startOfString){
                //create a substring until the char at start of string is encountered 
                i++;
            }else{
                if(str.split(str.substring(0,i)).length == 0){
                    return true;
                }else{
                    //false alarm. continue matching.
                    i++;
                }
            }
        }
        return false;
    }
}

我知道我花了太多时间。

3 个答案:

答案 0 :(得分:3)

这实际上是单线解决问题的方法。 重复给定的字符串两次,并删除新创建的字符串的第一个和最后一个字符,检查给定的字符串是否为新创建的字符串的子字符串。

def repeatedSubstringPattern(self, s: str) -> bool:
     return s in (s + s )[1: -1]

例如:

  1. str: 阿巴 重复str:abababab。 删除第一个和最后一个字符:bababa。 检查abab是否是bababa的子串。
  2. str:aba。 重复str:abaaba 删除第一个和最后一个字符:baab。 检查aba是否是baab的子字符串。

数学证明:

让P为在字符串S中重复K次的模式。

S = P * K。

通过重复字符串S,让N为新创建的字符串。

N = S + S。

让F为字符串N的第一个字符,L为字符串N的最后一个字符

N =(F + P *(K-1))+(P *(K-1)+ L)

N = F + P(2K-2)+ L

如果K = 1,即一个字符串仅重复一次

N = F + L。 //因为N!= S所以错

如果K≥2。

N = F + k'+ N

其中k'≥K。由于我们的S = P * K。 因此,S必须在N中。

我们可以进一步使用KMP算法来检查S是否为N的子字符串。这将使我们的时间复杂度为O(n)

答案 1 :(得分:0)

您可以使用Z-algorithm

  

给定长度为n的字符串S,Z算法产生一个数组Z.   其中Z [i]是从S [i]开始的最长子串的长度   它也是S的前缀,即最大k   对于所有0≤j<1,S [j] = S [i + j]。 ķ。注意,Z [i] = 0表示   S [0]≠S [i]中。为了便于术语,我们将参考子串   也是前缀作为前缀子串。

为您的字符串构建Z数组,并查找i是否存在此类位置i+ Z[i] = n,并且i是n的除数(字符串长度)

答案 2 :(得分:0)

一个简短易懂的逻辑是:

def repeatedSubstringPattern(s: str):
    for i in range(1,int(len(s)/2)+1):
        if set(s.split(s[0:i])) == {''}:
            return True 
    return False

您也可以写return i来返回数字,模式之后重复该数字。