String 搜索循环字符串

String 搜索循环字符串,string,data-structures,trie,cyclic,String,Data Structures,Trie,Cyclic,我正在寻找在数据结构(插入函数)中存储二进制字符串的最有效方法,然后在获取字符串时,我想检查给定字符串的某些循环字符串是否在我的结构中 我曾考虑将输入字符串存储在Trie中,但在尝试确定我现在得到的字符串中的某个循环字符串是否插入到Trie中时,意味着在Trie中搜索所有可能的循环字符串 有没有什么方法可以更有效地做到这一点,而场所的复杂性将类似于Trie 注意:当我说字符串的循环字符串时,我的意思是,例如1011的所有循环字符串都是:011111011011011011011011011011

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

我曾考虑将输入字符串存储在Trie中,但在尝试确定我现在得到的字符串中的某个循环字符串是否插入到Trie中时,意味着在Trie中搜索所有可能的循环字符串

有没有什么方法可以更有效地做到这一点,而场所的复杂性将类似于Trie


注意:当我说字符串的循环字符串时,我的意思是,例如
1011
的所有循环字符串都是:
011111011011011011011011011011011011011011011011011011011
你能根据以下内容想出一个循环字符串的规范化函数吗:

  • 查找最大的零运行
  • 旋转字符串,使零的运行在前面
  • 对于大小相等的每一行零,请查看将其旋转到前面是否会产生一个按字典顺序排列的较小字符串,如果是,请使用该字符串
  • 这将把等价类(1011111011010111)中的所有内容规范化为字典最小值0111

    0101010101
    是一个棘手的例子,该算法无法很好地执行,但是如果您的位是大致随机分布的,那么它在长字符串的实践中应该可以很好地工作

    然后,您可以基于规范形式进行散列,或者使用仅包含空字符串和以0开头的字符串的trie,一次trie运行将回答您的问题

    编辑:

    如果我有一个长度为| s |的字符串,可能需要很多时间才能找到最小的字典值。实际需要多少时间

    这就是为什么我说,
    010101….
    是一个性能很差的值。假设字符串的长度为n,1的最长行程的长度为r。如果位是随机分布的,则最长运行的长度是O(logn)

    找到最长行程的时间是O(n)。可以使用偏移量而不是缓冲区拷贝来实现移位,缓冲区拷贝应为O(1)。运行次数为最坏情况O(n/m)

    然后,执行步骤3的时间应为

  • 查找其他长时间运行:一次O(n)通过,O(logn)存储平均情况,O(n)最坏情况
  • 对于每次运行:O(对数n)平均情况,O(n)最坏情况
  • 按字典顺序移位和比较:O(logn)平均情况,因为大多数随机选择字符串的比较都会提前失败,O(n)最坏情况

  • 这导致最坏的情况是O(n²),但平均情况是O(n+log²n)≅ O(n)。

    您有n个字符串s1..sn,给定一个字符串t,您想知道t的循环置换是否是任何s1..sn的子字符串。您希望尽可能高效地存储字符串。我正确理解你的问题了吗


    如果是这样,这里有一个解决方案,但是运行时间很长:对于给定的输入t,让t'=concat(t,t),检查s1..sn中每个s的t',看看t'和sm的最长子序列是否至少是| t |如果| si |=k,| t |=l,它在O(n.k.l)时间内运行。您可以将s1..sn存储在您想要的任何数据结构中。这够好还是你够好

    如果这是针对多于这两个字符的字母表,我会说创建一个哈希函数,该函数生成相同的结果,而不管字符值的顺序如何,这样您就可以快速消除大多数不匹配项。@C.Evenhuis:不,我只处理二进制字符串。您是否预先进行了所有插入?或者你混合了插入和查找吗?@templatetypedef:混合插入和查找我不明白。假设存储1100010,搜索1001。你的算法是如何进行的?它能找到子字符串1100吗?不,它不能解决循环字符串的子字符串,但我在OP中没有看到任何关于子字符串的内容。嗯,我对“检查某个循环..是否在我的结构中”的解释是不同的。也许user550413会澄清。@Ali:不,我不关心子字符串,但我不确定我是否有这个想法。如果我有一个像11001001这样的字符串,那么在执行步骤1-3之后,最小的字典值将是00100111或00111001,那么我将插入哪一个?如果我取第一个(其他stirng中可能有许多其他选项)并将其插入Trie,然后通过步骤1-3检查01001110这样的字符串,我会将其转换为00111001(第二个选项),但找不到它。@MikeSamuel:好的,我错过了上面评论中的第3步,但是如果我有一个长度为| s |的字符串,可能需要很多时间才能找到最小的字典值。实际需要多少时间?