Algorithm 无限流中代币替换的有效算法

Algorithm 无限流中代币替换的有效算法,algorithm,stream,hashmap,hashtable,Algorithm,Stream,Hashmap,Hashtable,给定一个字符串映射,例如: {'ABC': 'BCD', 'key': 'book',........} 以及无限的文本流,例如: "Sally had a key and a book with the ABC..." 用对应的值替换字符串映射中与键匹配的每个令牌的有效算法是什么 输出: "Sally had a book and a book with the BCD..." 除了简单地拆分传入令牌并查询字符串映射以进行包含(一个O(1)操作)之外,还能做得更好吗 代码将驻留在Web服

给定一个字符串映射,例如:

{'ABC': 'BCD', 'key': 'book',........}
以及无限的文本流,例如:

"Sally had a key and a book with the ABC..."
用对应的值替换字符串映射中与键匹配的每个令牌的有效算法是什么

输出:

"Sally had a book and a book with the BCD..."
除了简单地拆分传入令牌并查询字符串映射以进行包含(一个O(1)操作)之外,还能做得更好吗


代码将驻留在Web服务器上——用户获得转换输出的速度越快越好。

好吧,您正在寻找的算法至少与您正在读取的令牌数成线性关系(因为您最多只能对流中的每个令牌执行恒定数目的操作),因此,这里不会有任何改进,因为我假设在您的输入流中没有特殊的冗余或模式(我们可能会滥用它们来提高效率)

对于映射,最有效的解决方案可能是对映射的键进行二叉搜索树——对于包含n个项的映射,我们只需将每个标记与n个不同的键进行比较

如果您的问题没有任何进一步的限制,我怀疑您会得到比这更有效的结果——m令牌的最坏情况复杂性O(m logn)和n个键值对的映射


这很好,但并不可怕;非常重要的问题:有什么方法可以利用您的数据吗?

好吧,您正在寻找的算法在您读取的令牌数量方面至少是线性的(因为您最多会对流中的每个令牌执行恒定数量的操作),所以不会有任何改进,正如我所假设的,在您的输入流中没有特殊的冗余或模式(我们可以利用这些冗余或模式来提高效率)

对于映射,最有效的解决方案可能是对映射的键进行二叉搜索树——对于包含n个项的映射,我们只需将每个标记与n个不同的键进行比较

如果您的问题没有任何进一步的限制,我怀疑您会得到比这更有效的结果——m令牌的最坏情况复杂性O(m logn)和n个键值对的映射


这很好,但并不可怕;非常重要的问题:有什么方法可以利用您的数据吗?

如果您使用。只要让叶节点上的输出状态返回替换字符串即可


这可能比将文本拆分为标记要快,因为您不必管理字符串。这是一个字一个字的。您必须测试比使用哈希表查找快多少。这也比简单的哈希表查找更难实现。

如果使用。只要让叶节点上的输出状态返回替换字符串即可


这可能比将文本拆分为标记要快,因为您不必管理字符串。这是一个字一个字的。您必须测试比使用哈希表查找快多少。这也比简单的哈希表查找更难实现。

我猜您实际上是在寻找一种更高级语言(node.js?python?)的高效解决方案;一般来说,如果您使用这样一种语言,最好使用该语言本机支持的数据结构,即Python中的字典和Javascript中的对象。你可能已经知道了

如果您是用较低级别的语言编写的,那么您可能希望选择一种优化,这种优化不需要为每个单词不必要地构造字符串对象,前提是绝大多数单词不会受到替换的影响。一种方法是使用一个字符一个字符的散列算法,在读取输入字符时进行计算,每次开始一个新词时进行重置。当到达单词末尾时,如果某个目标具有该哈希值,则可以签入average
O(1)
time。如果没有,就继续读下去。只要保留当前字,就可以周期性地将输入缓冲区刷新到输出

如果目标很长(可能不是这种情况),您可以通过存储目标字符串前缀(或某些前缀)的哈希值来避免保留当前单词。然后,当输入缓冲区用完时,可以检查当前哈希值是否与适当长度的前缀之一的哈希值匹配。偶尔检查此表单还可以解决故意创建哈希冲突的DoS攻击(尽管在您的情况下,这并不是什么问题;攻击者所能做的只是强迫您对每个单词进行全文比较;他们无法将自己的单词添加到哈希表中)


然而,如果我用C这样的低级语言编写这段代码,我可能会将目标词放入一个trie中,并跟踪每个输入字符的trie。一旦trie中没有匹配项,就可以刷新到当前单词的末尾;这很可能发生在所有不匹配的词的早期,甚至可能发生在它们的第一个字符上。尽管trie通常需要比哈希映射更多的存储空间(甚至可能需要比BST更多的存储空间),但也有存储压缩技术(如果可以提前设置数据结构的话)提前停止检查单词的能力可能是一种成功。

我猜您实际上是在寻找一种更高级语言(node.js?python?)的高效解决方案;一般来说,如果您使用这样一种语言,最好使用该语言本机支持的数据结构,即Python中的字典和Javascript中的对象。你可能已经知道了

如果你
pos:                     1                   2
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6   <-- slot 26 is reserved for 
val: A 0 0 D 0 0 G 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0       "end of map token"
     |     |     |
     B     E     H   <-- sub buckets don't show all buckets as in the top level, but they
    / \    |     |       are all there.
   C   D   F     END
  /    |    \
END   END   END
Input: ABC
    1: look up location 'Z' - 'A' = 0
    2: is there anything in this bucket? yes
    3: look in sub-buckets.  
    4: Is there anything in the 'Z'- 'B' bucket? yes
    5: look in sub buckets.
    6: Is there anything in the 'Z' - 'C' bucket? yes
    7: look in sub-buckets
    8: reached end of input token.  Is end of map bucket is marked? yes
    9: match found
Input: ABCD  (input token longer than closest match in map)
    1: look up location 'Z' - 'A' = 0
    2: is there anything in this bucket? yes
    3: look in sub-buckets.  
    4: Is there anything in the 'Z'- 'B' bucket? yes
    5: look in sub buckets.
    6: Is there anything in the 'Z' - 'C' bucket? yes
    7: look in sub-buckets
    8: Is there anything in the 'Z' - 'D' bucket? no
    9: match not found  
Input: ABE
    1: look up location 'Z' - 'A' = 0
    2: is there anything in this bucket? yes
    3: look in sub-buckets.  
    4: Is there anything in the 'Z'- 'B' bucket? yes
    5: look in sub buckets.
    6: Is there anything in the 'Z' - 'E' bucket? no
    7: match found