搜索循环字符串

时间:2012-01-20 14:49:55

标签: string data-structures trie cyclic

我正在寻找在数据结构中存储二进制字符串的最有效方法(插入函数),然后在获取字符串时,我想检查给定字符串的某个循环字符串是否在我的结构中。

我考虑过将输入字符串存储在Trie中,但是当我试图确定我现在获得的字符串的某个循环字符串是否插入Trie意味着要进行| s |在Trie中搜索所有可能的循环字符串。

有没有办法更有效地做到这一点,而地方复杂性就像在特里?

注意:当我说一个字符串的循环字符串时,我的意思是例如1011的所有循环字符串都是:0111, 1110, 1101, 1011

2 个答案:

答案 0 :(得分:5)

您是否可以根据以下内容为循环字符串提供规范化函数:

  1. 找到最大的零点。
  2. 旋转字符串,使前面的零行数位于前面。
  3. 对于每个相同大小的零运行,请查看向前旋转是否会产生字典上较小的字符串,如果是这样,请使用它。
  4. 这会将等价类(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步的时间应为

    1. 查找其他长期运行:一个O(n)通过O(log n)存储平均情况,O(n)最坏情况
    2. 对于每次运行:O(log n)平均情况,O(n)最坏情况
    3. 按字典顺序移位和比较:O(log n)平均情况,因为大多数比较随机选择的字符串早期失败,O(n)最坏情况。
    4. 这导致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存储在您想要的任何数据结构中。那还不够好吗?