是否有任何有效的算法来检查二进制字符串是否是周期性的?
设S为二进制字符串,H为S的子字符串集合。如果S可以通过连接一次或多次,H中至少有一个h,也是h!=,则称S是周期性的。 S.
答案 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
}