判断字符串是否相等可以在常数时间内完成,strcmp()可以在 log(n) 的时间内完成.这看起来很酷,然而计算机科学家会告诉你这被证明是不可能的,但是这对于处理字符串的问题依然是很有用的,让我们来学习一下吧.
设
M
是一个大质数(
然后对于任何一个字符串
S
,
因此,要判断 S1 是否等于 S2 ,你就可以直接比较 H(S1) 和 H(S1) ,错的概率最多是 1/M 。
但是这需要花费 O(|S|) 的时间计算出 H(S) ,我们真的保存了所有的东西么?
假设我们只关心一些字符串的子串
S=a0...an
.首先对于每一个在
[0,n]
的
i
计算出
如果我想比较多个字符串怎么办?
假设你想比较
如果我想…实际的比较?
我们已经做了相等测试,如果我们想实际比较两个字符串怎么办?让我们考虑 S1 和 S2 的实际比较是怎样进行的.我们查找 S1 和 S2 的第一个不同的字符并做比较.所以查找 S1 和 S2 有多少字符匹配就足够了.我们可以二分查找这个数字,因为字符串相等测试可以在常数时间内完成,所以strcmp()现在是 log(n) 的时间了.
你骗人!
你需要在开始时计算并且存储P,而这并没有计算在你的”常数时间”内.
确实如此,但是你首先需要把这些字符串先存起来,你需要花费时间来读入,花费空间来存放.计算P需要1个时间的花费,如果你能承受初始时将这些字符串都读进来的花费,你一定能承受这1个时间的花费.
如果 M 是
109+7 , 计算 2M−1 代价很大.
确实如此,你应该预处理算出所有需要的2的幂,特别的: 20,21,...,2|S|−1,2M−1,2M−2,2M−|S| .这是另外2|S|的需要预处理的东西,所以,再说一遍,这很廉价.
这并不是真的有效,它有 1/M 的几率是错的.
确实如此,如果你担心,你可以用和定义H同样的方法来定义 H2 (除了你需要给 H2(c) 一个不同的值),两个字符串相等则需要 H(S1)==H(S2) && H2(S1)==H2(S2) ,这样错的可能性就降到了 1/M2=1/1018 ,这样应该能使你高兴.除非你是Goolge或者是其他什么才会定义 H3,H4 甚至是 H5 .
但这还是错的,就算仅有 1/1045 的几率是错的,这依然是错的.
不,这真的不会的,你知道宇宙射线实际上会使内存上的某些bit位反转?(这是不是很酷?)Intel估计每256MB的内存每个月发生一次会这样的情况?所以宇宙射线选择某个确切的时钟周期并反转了你正在做比较的bit位的几率大约是
1/1024
,但是你不要到处乱说
“我的程序因为宇宙射线而不是很对.”你甚至从未考虑到宇宙射线,那又为什么去把时间浪费在担心这
1/1045
的几率的失败?