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你认为重复模式是什么?@irabakterabaa
是重复的。@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]