Regex 语言无关:检查字符串是否由某个子字符串的倍数组成

Regex 语言无关:检查字符串是否由某个子字符串的倍数组成,regex,language-agnostic,pattern-matching,Regex,Language Agnostic,Pattern Matching,我希望通用算法能够发现字符串是否包含重复模式,并且字符串的任何部分都不会被遗漏在重复模式之外 例如,查看以下示例字符串: abcabcabc - true abcabcabcx - false cucumbercucumber - true cucumber - false abaaabaaabaa - true 我查看了,它在一些情况下解决了问题,但在cumber示例中会失败。我需要在任何情况下都能工作的东西。这似乎是一个显而易见的方法: String s = "abaaabaabaa" ;

我希望通用算法能够发现字符串是否包含重复模式,并且字符串的任何部分都不会被遗漏在重复模式之外

例如,查看以下示例字符串:

abcabcabc - true
abcabcabcx - false
cucumbercucumber - true
cucumber - false
abaaabaaabaa - true

我查看了,它在一些情况下解决了问题,但在
cumber
示例中会失败。我需要在任何情况下都能工作的东西。

这似乎是一个显而易见的方法:

String s = "abaaabaabaa" ; // string to test

for (int repeating_pattern_length=1; 
     repeating_pattern_length<=s.length/2;
     repeating_pattern_length++)
{  if (modulo(s.length,repeating_pattern_length)==0)
   { // can fit exactly N times
     String proposed_subpattern=s.substring(0,repeating_pattern_length);
     for (nth_instance=2; // don't need to check 1st occurrence
          nth_instance<=s.length/repeating_pattern_length;
          nth_instance++)
     { // check nth occurrence
       if (!proposed_subpattern.equal(
           s.substring((nth_instance-1)*repeating_pattern_length,
                       repeating_pattern_length)
          cycle repeating_pattern_length; // nth occurrence doesn't match
     }
     return true;
   }
}
return false;
String s=“abaabaa”//要测试的字符串
对于(int-repeating_-pattern_-length=1;

重复_pattern _length因为您不需要特定的语言,我建议您查看Rosetta的代码页。您可以找到并研究解决此问题的一系列算法。 尽管问题在Rosetta代码中针对1和0进行了说明,但大多数解决方案都应适用于任何可能的字符串

我已经编写了一个通用的Lisp递归解决方案,下面是注释代码:

(ql:quickload :alexandria)
(defun rep-stringv (a-str &optional (max-rotation (floor (/ (length a-str) 2))))
  ;; Exit condition if no repetition found.
  (cond ((< max-rotation 1) "Not a repeating string")
        ;; Two checks:
        ;; 1. Truncated string must be equal to rotation by repetion size.
        ;; 2. Remaining chars (rest-str) are identical to starting chars (beg-str)
        ((let* ((trunc (* max-rotation (truncate (length a-str) max-rotation)))
                (truncated-str (subseq a-str 0 trunc))
                (rest-str (subseq a-str trunc))
                (beg-str (subseq a-str 0 (rem (length a-str) max-rotation))))
           (and (string= beg-str rest-str)
                (string= (alexandria:rotate (copy-seq truncated-str) max-rotation)
                         truncated-str)))
         ;; If both checks pass, return the repeting string.
         (subseq a-str 0 max-rotation))
        ;; Recurse function reducing length of rotation.
        (t (rep-stringv a-str (1- max-rotation)))))
最好的解决方案是使用字符串的a,正如您现在可能已经知道的那样-因为这是一个到处都在描述的常见问题,例如


实现它对我来说似乎是多余的,除非你真的需要性能。在任何情况下,可以找到后缀树(多语言)的例子。

< P>这里有一些C++的代码来完成这个任务:

bool IsRepeating( std::string in ) {

    int totalLength = in.length();
    for (int subLength = 1; subLength <= totalLength / 2; subLength++ ) {
        if (totalLength % subLength != 0) continue;

        for (int startPos = 0; startPos < subLength; startPos++) {
            char startChar =in[startPos];
            bool mismatchFound = false;
            for (int delta = subLength; delta < totalLength-startPos; delta += subLength) {
                if (in[startPos+delta] != startChar ) {
                    mismatchFound = true;
                    break;
                }
            }
            if (mismatchFound) {
                break;
            }
            return true;
        }
    }
    return false;
}
bool-IsRepeating(std::string-in){
int totalength=英寸长度();

对于(int subLength=1;subLength,受is启发的Python解决方案


这需要
O(n)
时间假设一个
str的有效实现。确实有一个有趣的问题。到目前为止,我所学到的是,对于每个
正则表达式
都有一个
有限自动机
。第一个问题应该是
动态模式识别有一个有限自动机吗?
。如果有,你可以理解将其转换为正则表达式,反之亦然。如果支持反向引用,则可以由正则表达式执行:
^(+)\1+$
解释为什么这个例子是正确的:abaabaaabaaa你认为重复模式是什么?@irabakter
abaa
是重复的。@SebastianProske:啊。是的。好吧。这就是为什么你想要一个算法而不是一个人来做这件事。或者至少为什么你想要一个算法而不是我来做:-}也许我不明白这是怎么回事。这和s==“a”有什么关系?
s+s==“aa”
,所以
(s+s)[1:-1]==“s”(空字符串)。因此
s in(s+s)[1:-1]
返回
False
。啊,这是零原点索引。(我不是Python专家).有趣。所以这个想法应该可以在任何带有字符串concat、substring和find的语言中实现。
bool IsRepeating( std::string in ) {

    int totalLength = in.length();
    for (int subLength = 1; subLength <= totalLength / 2; subLength++ ) {
        if (totalLength % subLength != 0) continue;

        for (int startPos = 0; startPos < subLength; startPos++) {
            char startChar =in[startPos];
            bool mismatchFound = false;
            for (int delta = subLength; delta < totalLength-startPos; delta += subLength) {
                if (in[startPos+delta] != startChar ) {
                    mismatchFound = true;
                    break;
                }
            }
            if (mismatchFound) {
                break;
            }
            return true;
        }
    }
    return false;
}
bool IsRepeating( const std::string& in ) {
    if (in.length() < 1) return false;
    return (in + in).substr(1, 2 * in.length() - 2).find(in) != std::string::npos;
}
s in (s + s)[1:-1]