该算法对查找字符串的周期是否正确?

时间:2018-11-13 03:47:28

标签: c string algorithm

this question的回答引用了Crochemore和Rytter的“文本算法”的第340页,该文本用于线性时间算法来计算字符串的周期。但是,它非常复杂,下面的代码是根据双向算法(由Chrochemore和Perrin编写)使用的最大后缀算法改编而成,对于计算周期似乎是正确的:

size_t period_of(const char *x)
{
    size_t j=1, k=0, p=1;
    while (x[j+k]) {
        if (x[j+k] != x[k]) {
            j += k?k:1;        // Previously: j += k+1;
            k = 0;
            p = j;
        } else if (k != p) {
            k++;
        } else {
            j += p;
            k = 0;
        }
    }
    return p;
}

从其改编的《双向》中的版本计算出最大后缀的周期,这是计算最大后缀的副作用。但是,除非我缺少什么,否则逻辑的有效性似乎并不取决于最大后缀属性。

以上是否正确?如果没有,您能否提供一个显示失败之处的反例?

1 个答案:

答案 0 :(得分:0)

即使在修复后,也有一个反例:

aabaaaba

在位置3,该算法首先开始匹配3期匹配的前缀。但是,当它在位置5获得a而不是b时,会错误地将候选时间段增加到5,从而错过了实际时间段4。

“双向”算法的改编自该算法,该算法计算最大后缀的周期,这是查找最大后缀的副作用,确实依赖于最大后缀属性。它具有!=>这两个条件,而不是<条件,其中两个条件之一将替换候选后缀的开始,另一个条件将延长运行时间。非严格地说,不会出现上述情况,因为b > a(在这种情况下,后缀将从b开始,或者a > b,在这种情况下,{{1})开始}。我怀疑更详细地阅读本文(这需要使用基于一个的索引来破译其可怕的伪代码表示法)才能使其余部分变得清晰。

不幸的是,我相当确信我所询问的算法不可恢复。

还要注意,在示例中,aaa > aab不必是单个字符。它可以是任意长的模式。这似乎排除了任何琐碎的线性时间修正。