Algorithm 发现字符串中连续的重复模式

Algorithm 发现字符串中连续的重复模式,algorithm,pattern-matching,data-compression,Algorithm,Pattern Matching,Data Compression,我试图搜索字符串中重复子字符串的最大数量,以下是一些示例: "AQMQMB" => QM (2x) "AQMPQMB" => <nothing> "AACABABCABCABCP" => A (2x), AB (2x), ABC (3x) “AQMQMB”=>QM(2x) “AQMPQMB”=> “aacabcp”=>A(2x)、AB(2x)、ABC(3x) 如您所见,我只搜索连续的子字符串,这似乎是一个问题,因为所有压缩算法(至少我知道)都不关心连续性(),或

我试图搜索字符串中重复子字符串的最大数量,以下是一些示例:

"AQMQMB" => QM (2x)
"AQMPQMB" => <nothing>
"AACABABCABCABCP" => A (2x), AB (2x), ABC (3x)
“AQMQMB”=>QM(2x)
“AQMPQMB”=>
“aacabcp”=>A(2x)、AB(2x)、ABC(3x)
如您所见,我只搜索连续的子字符串,这似乎是一个问题,因为所有压缩算法(至少我知道)都不关心连续性(),或者太简单,无法处理连续模式而不是单个数据项()。我认为由于同样的问题,使用相关的算法也没有用

我认为有一些生物信息学算法可以做到这一点,有人知道这种算法吗

编辑
在第二个示例中,可能存在连续模式的多种可能性(感谢您的通知,请阅读下面的注释),但是在我的用例中,这些可能性中的任何一种都是可以接受的。

后缀树相关算法在这里很有用

其中一个在(第9.6章)中描述。它结合使用分治方法和后缀树,时间复杂度为O(N logn+Z),其中Z是子串重复的次数


同一本书描述了这个问题的更简单的O(N2)算法,也使用了后缀树。

这是我在类似问题中使用的:

<?php

$input="AACABABCABCABCP";

//Prepare index array (A..Z) - adapt to your character range
$idx=array();
for ($i="A"; strlen($i)==1; $i++) $idx[$i]=array();

//Prepare hits array
$hits=array();

//Loop
$len=strlen($input);
for ($i=0;$i<$len;$i++) {

    //Current character
    $current=$input[$i];

    //Cycle past occurrences of character
    foreach ($idx[$current] as $offset) {

        //Check if substring from past occurrence to now matches oncoming
        $matchlen=$i-$offset;
        $match=substr($input,$offset,$matchlen);
        if ($match==substr($input,$i,$matchlen)) {
            //match found - store it
            if (isset($hits[$match])) $hits[$match][]=$i;
            else $hits[$match]=array($offset,$i);
        }
    }

    //Store current character in index
    $idx[$current][]=$i;
}

print_r($hits);

?>

我怀疑它是O(N*N/M)时间,N是字符串长度,M是字符范围的宽度

它输出我认为是您示例的正确答案

编辑:

该算法的优点是在运行时保持有效的分数,因此它可以用于流,只要您可以通过一些缓冲来查看数据。这是有效率的

编辑2:


如果允许重复检测的最大长度,这将减少空间和时间使用:通过类似于
If($matchlen>MAX\u MATCH\u LEN)…的方式排除太“早”的过去事件。
限制索引大小和字符串比较长度

我从您的示例中看到最小长度为2,是否也有最大长度?这会影响内存需求。不,没有最小/最大长度限制,我将修改示例的输出,感谢您通知meAre您确定示例的结果吗?我会将“CAB”和“BCA”(各2个)添加到结果列表中!我认为字符串可以有不同连续模式的多个组合,因为它可能取决于算法的工作方式,例如,它是使用候选匹配表还是遍历后缀树,我还不太确定,但我只是想指出,根据我的用例,这些组合中的任何一种都很好。我认为时间复杂度是O(N^3/M)-两个循环和一个字符串比较。虽然你是对的,字符串比较会带来更大的复杂度,但我不会认为它是O(N):它只比较比当前索引短的子字符串,不是字符串的总长度。它添加了O(matchlen),保证远远低于O(N)。请您提供更多关于该算法的参考资料好吗?目前还没有正式的参考资料,它是从一个快速破解开始的,灵感来自通过回溯引用进行的字符串匹配。其思想是,模式的每一次重复都必须以相同的字符开始。因此,我保留了一个过去发生的索引(编辑2中的inifinte或finite),对于看到的每个字符,该索引为我提供了一个可能的重复起点列表。其想法是,这些参考列表将相对较短,从而节省比较。