我有一个0和1的字符串。将“连续双精度”定义为立即重复的子串。例如,字符串“011101010101110”可以分解为“011 1010 1010 1110”,可以压缩为“011(1010)1110”。
是否有一个很好的算法来查找字符串中的所有连续双精度数?我能想到的最好的是关于字符串长度的二次方:
def all_contiguous_doubles(s):
for j in range(len(s)):
for i in range(j):
if s[i:j] == s[j:2*j - i]:
print "%s(%s)%s" % (s[:i], s[i:j], s[2*j - i:])
答案 0 :(得分:1)
这里我介绍我的动态编程解决方案,其时间复杂度为 O(n ^ 2)和 空间复杂度为O(n ^ 2),其中n是原始字符串的长度。
下面我递归地定义函数dl(r,c)。 如果你让dl(r,c)成为一个表并且以正确的顺序填充,你将在O(n ^ 2)中完成它。
定义:
char(i)=位置i的字符
substr(i)=从位置i开始到原始字符串结尾的子字符串。
dl(r,c)= substr(r)和substr(c)的公共非重叠前缀的长度。
dl(r,c)的递归定义:
由于dl(r,c)是对称的,我们只考虑r <= c。
当r == c时,dl(r,c)= 0。 因为如果子串在同一点开始,它将始终重叠。
当char(r)!= char(c)时,dl(r,c)= 0。 因为前缀不一样。
if char(r) == char(c), if dl(r+1,c+1) + 1 < c-r dl(r,c) = dl(r+1,c+1) + 1 else dl(r,c) = dl(r+1,c+1)
dl(r,c)
的最大值dl(r,c) == c-r
将是您的答案。
答案 1 :(得分:0)
我会使用正则表达式提及/(.+)$1/
这是一个简单的算法,否则可能会起作用:
创建一个功能
get_largest(string, i, j)
返回i和j之间的最大双倍。
我会使用min_s的hash_size(20,(j-i)// 2)
现在说你的hash_size是20,找到长度为20的最不频繁的子字符串以及它出现的所有位置。 (这可以使用哈希表快速完成)
现在让我们说它被发现的位置是[10,110,320,500,..] 查看字符串[10:110],字符串[110,320],字符串[320,500] ..等。 如果这些子字符串中的任何一个出现多次,请找到这些子字符串的所有位置,并使用上面的技术或其修改版本检查双重字符串。
如果您还没有找到包含长度为20的最不常见的子字符串的double,我们现在可以递归地划分并征服以搜索所有不包含最不常见子字符串的最长子字符串。
希望在大多数情况下这应该很快。
答案 2 :(得分:0)
如果压缩确实是你的最终目标:
为什么没有一个大小为16的查找表将字符串“0000”“0001”,“1010”等映射到它们各自的十六进制数字'0-F'?
存储表示时:将二进制字符串转换为十六进制字符串序列?
您可能还想在Grey Code上查找。在二进制序列中,前一个数字和当前正好相差1位。
如果我们在表格中有格雷码表示0-F,那么:
对于十六进制字符串中的字母:检查前一个或当前字母是否为“格雷码”顺序中的相应字母。如果是这样,您可以进一步压缩它。 (不同的位也可以在中间 - 某些情况必须正确处理')