我一直在尝试使用分隔符序列化一些数据并遇到问题。
如果它包含一个分隔符,我希望能够快速找到一个不是给定字符串的子字符串的字符串,这样我就可以将它用作分隔符。
如果我不关心大小,找到它的最快方法是检查给定字符串中的字符,并选择一个不同的字符,制作给定字符串长度仅为该字符的字符串。
可能有办法进行某种检查,首先测试中间字符,然后测试第一段和最后一段的中间...但我没有看到明确的算法。
我目前的想法,相当快,但不是最佳的 初始化一个散列,所有字符都作为键,0作为计数 使用哈希计算字符串字符作为字节。
找到最少数量的字符。如果我找到一个零字符的话,立即停止。
使用该字符数加1作为分隔符。
我相信那是O(n),虽然显然不是最短的。但是分隔符总是不会超过n / 256 + 1个字符。
我也可以尝试某种基于trie的构造,但是我不太确定如何实现它,那0(n ^ 2)对吗?
可能会有帮助。
答案 0 :(得分:1)
你的字符计数方法是不够的,因为你只是在谈论当前的字符串。分隔符的重点在于理论上你将多个字符串分开,因此你需要统计所有字符串。
我看到两种可能的替代解决方案
选择一个分隔符并转义字符串中的分隔符。
可以使用URI::Escape
来转义特定字符,例如&
,并将其用作分隔符。
因为我已经在替代解决方案的列车上,不妨提出所有其他序列化模块:Comparison of Perl serialization modules
我喜欢像这样的任务背后的理论,但是像XY Problem
答案 1 :(得分:1)
我同意@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。初始化和内存将是昂贵的。这值得吗?也许不是。
如果使用了所有字符,我会使用随机方法:猜一个分隔符,然后扫描字符串以验证它没有被包含。
如何以谨慎的方式进行猜测?