周期性二进制字符串

时间:2011-11-24 07:27:51

标签: algorithm

是否有任何有效的算法来检查二进制字符串是否是周期性的?

设S为二进制字符串,H为S的子字符串集合。如果S可以通过连接一次或多次,H中至少有一个h,也是h!=,则称S是周期性的。 S.

5 个答案:

答案 0 :(得分:9)

长度为Len的初始字符串S.将字符串加倍(实际上我们需要S +一半的S)。搜索双字符串SS中的初始字符串S的出现,从第2个位置开始,以Len / 2 + 1结束。如果位置P存在这种情况,那么S是周期性的,周期为P-1。

S = abbaabbaabba Len = 12 SS = abbaabbaabbaabbaabbaabba

从第2位搜索到第7位,S在P = 5处发现,周期= 4

S = abaabaabaabb SS = abaabaabaabbabaabaabaabb

S不会出现在SS中(1和L + 1除外),不存在句号

P.S。注意由于有用的Venkatesh评论: 我们需要添加最小可能的周期单位,对于偶数大小的字符串,它的长度是L / 2,对于奇数大小的字符串,它的最大除数是L(如果长度是素数,则字符串不能是周期性的)。简单因子分解方法具有O(N ^ 1/2)复杂度,更复杂 - O(N ^ 1/4),因此有时需要对长度进行分解以避免不必要的长字符串比较。

答案 1 :(得分:3)

我很确定有可能对此进行改进,但我会先打破S的长度(我称之为L)为素数因子,然后检查S / f的长度。对于每个素数因子f(len(h)必须除以len(S)并且我因为没有寻找最短的h,所以素数L / len(h)就足够了。

至于改进,随机检查顺序在某些情况下会有所帮助(以防止为更糟糕的情况构建输入等)。

答案 2 :(得分:1)

首先要发生这种情况,长度(h)必须除以长度(S)。

如果是k = length(S)/length(h),那么对于给定的k,可以很容易地检查字符串是否是周期性的。

实际上,如果S表示的数字可以被100..0100..0 ... 100..0整除,则它是周期性的。 这是长度为(S)的数字,具有相等长度的k个块,每个块只有最高位集。

答案 3 :(得分:1)

private static boolean isPeriodic(String string) {
int stringLength = string.length();
if (stringLength <= 1) {
    return false;
}
boolean flag = true;

for (int i = 1; i <= stringLength / 2; i++) {
if (string.length() % i == 0) {
if (flag && i > 1) {
    return flag;
}
flag = true;
for (int j = i; j < stringLength;) {

if ((j + i) <= stringLength) {

if (string.substring(0, i).equals(
        string.substring(j, j + i))) {
    j = j + i;
    continue;
} else {
    flag = false;
    break;

}
} else {
    break;
}

}
}

}
return flag;
}

答案 4 :(得分:0)

这是O(m + (n-1))算法的实现(其中m是输入长度,n是周期长度)。

基于Knuth Morris Pratt算法,它迭代输入字符串,检查子串input[0:i]是否是重复模式。如果它在输入字符串中找到模式中没有的字符,则i将更新为该字符的索引。这意味着字符串中的字符不会被多次比较。

public static String findSequence(String input) {
  out: for (int i = 0; i < input.length();) {
    for (int j = i; j < input.length(); j++) {
      if(input.charAt(j % (i+1)) != input.charAt(j)) {
        i = j;
        continue out;
      }
    }
    return (String) input.subSequence(0, i + 1);
  }
  return ""; // Impossible
}