【问题标题】:quickly find a short string that isn't a substring in a given string快速找到一个不是给定字符串中的子字符串的短字符串
【发布时间】:2014-05-24 22:54:03
【问题描述】:

我一直在尝试使用分隔符序列化一些数据并遇到问题。

如果它包含分隔符,我希望能够快速找到不是给定字符串的子字符串的字符串,以便我可以将其用作分隔符。

如果我不关心大小,找到它的最快方法是检查给定字符串中的一个字符,然后选择一个不同的字符,创建一个给定字符串的长度仅为该字符的字符串。

可能有一种方法可以进行某种检查,首先测试中间字符,然后测试第一段和最后一段的中间......但我没有看到明确的算法。

我目前的想法是相当快但不是最优的 使用所有字符作为键和 0 作为计数初始化哈希 使用哈希值将字符串字符读取为字节。

遍历键找到最少的字符数。如果我发现一个字符为零的字符,则立即停止。

使用该字符数加一作为分隔符。

我相信这是 O(n),尽管显然不是最短的。但是分隔符总是不超过 n/256 + 1 个字符。

我也可以尝试某种基于 trie 的构造,但我不太确定如何实现,那就是 0(n^2) 对吗?

https://cs.stackexchange.com/questions/21896/algorithm-request-shortest-non-existing-substring-over-given-alphabet

可能会有所帮助。

【问题讨论】:

  • 类似问题here有几个答案。

标签: regex string perl substring


【解决方案1】:

您的字符计数方法是不够的,因为您只是在谈论当前字符串。定界符的全部意义在于,理论上您要分隔多个字符串,因此您需要计算所有字符串。

我看到了两种潜在的替代解决方案

  1. 选择一个分隔符并在字符串中转义该分隔符。

    可以使用URI::Escape 转义特定字符,例如&,并将其用作分隔符。

  2. 在发送之前指定字符串的大小。这样你就知道要拉多少个字符。本质上是packunpack

而且因为我已经在寻找替代解决方案,所以不妨提出所有其他序列化模块:Comparison of Perl serialization modules

我喜欢这样的任务背后的理论,但听起来太像XY Problem

【讨论】:

  • 不,但我有一个模块的标准分隔符。我实际上找到了解决方案,但我感兴趣的是理论。
  • 同意,我可以在这样的问题理论中迷失一天。不过这次采取了一定程度的自我控制,不会陷入这种情况:) 很高兴你找到了解决方案。
【解决方案2】:

我同意@Miller 的观点,您最好的选择是选择一个字符并在文本中转义。

但是,这不是你问的,所以我会尝试回答这个问题。

我认为这些字符串很长,因此查找分隔符是时间敏感的。

在直接的 Perl 中,散列的想法可能会尽可能快。作为原生 C 扩展,您可以做得更好。我这样说是因为我的经验是 Perl 数组访问由于某种原因非常慢,而且这个算法使用数组效果很好:

int n_used_chars = 0;
int chars[256], loc_of_char[256];
for (int i = 0; i < 256; i++) used_chars[i] = loc_of_char[i] = i;

for (int i = 0; i < string_length; i++) {
  char c = string[i];
  int loc = loc_of_char[c];
  if (loc >= n_used_chars) {
    // Character c has not been used before. Swap it down to the used set.
    chars[loc] = chars[n_used_chars];
    loc_of_char[chars[loc]] = loc;
    chars[n_used_chars] = c;
    loc_of_chars[c] = n_used_chars++;
  }
}
// At this point chars[0..n_used_chars - 1] contains all the used chars.
// and chars[n_used_chars..255] contains the unused ones!

这将是 O(n) 并且在实践中非常快。

如果所有字符都使用了怎么办?然后事情变得有趣了……有 64K 的两字节组合。我们可以使用上面的技巧,两个数组都是 64K。初始化和内存会很昂贵。值得吗?也许不是。

如果使用所有字符,我会使用随机方法:猜测一个分隔符,然后扫描字符串以验证它不包含。

如何谨慎猜测?

【讨论】:

  • 是的,我想要一些 O(n) 的东西,它总是可以工作的(即使我们有超过 64k 的数据)。
猜你喜欢
  • 1970-01-01
  • 2023-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多