我正在寻找在数据结构中存储二进制字符串的最有效方法(插入函数),然后在获取字符串时,我想检查给定字符串的某个循环字符串是否在我的结构中。
我考虑过将输入字符串存储在Trie中,但是当我试图确定我现在获得的字符串的某个循环字符串是否插入Trie意味着要进行| s |在Trie中搜索所有可能的循环字符串。
有没有办法更有效地做到这一点,而地方复杂性就像在特里?
注意:当我说一个字符串的循环字符串时,我的意思是例如1011
的所有循环字符串都是:0111, 1110, 1101, 1011
答案 0 :(得分:5)
您是否可以根据以下内容为循环字符串提供规范化函数:
这会将等价类(1011,1101,1110,0111)中的所有内容规范化为按字典顺序排列的最小值:0111。
0101010101
是一个棘手的实例,这个算法不能很好地运行,但是如果你的位大致是随机分布的,那么在实践中它应该可以很好地用于长字符串。
然后您可以根据规范表单进行哈希,或者使用仅包含空字符串的trie和以0开头的字符串,单个trie运行将回答您的问题。
编辑:
如果我有一个长度为| s |的字符串可能需要花费大量时间才能找到字典值最小的值。实际需要花费多少时间?
这就是为什么我说010101....
是一个表现不佳的值。假设字符串的长度为n,最长的1的长度为r。如果这些位是随机分布的,则根据"Distribution of longest run",最长运行的长度为O(log n)。
找到最长跑步的时间是O(n)。您可以使用偏移量而不是缓冲区副本来实现移位,缓冲区副本应为O(1)。运行次数最差情况为O(n / m)。
然后,第3步的时间应为
这导致O(n²)的最坏情况,但平均情况为O(n +log²n)≅O(n)。
答案 1 :(得分:0)
你有n个字符串s1..sn并给出一个字符串t你想知道t的循环排列是否是任何s1..sn的子字符串。并且您希望尽可能高效地存储字符串。我是否正确理解了您的问题?
如果是这样,这里有一个解决方案,但运行时间很长:对于给定的输入t,让t'= concat(t,t),检查t'与s1..sn中的每个s一起查看是否t'和sm的最长子序列至少为| t |如果| si | = k,| t | = l它在O(n.k.l)时间内运行。您可以将s1..sn存储在您想要的任何数据结构中。那还不够好吗?