简答:对于单字节分隔符,explode 的时间复杂度为Ο(N);但是对于多字节分隔符,它的时间复杂度是Ο(N2)。
implode 显然在 Ο(N) 中,因为它只是将各个部分粘合在一起。
扩展答案:basic algorithm of explode 是在 string 中搜索出现的 delimiter 并将包含的子字符串复制到一个新数组中。
为了在字符串中查找分隔符的位置,它使用internal function zend_memnstr(php_memnstr只是zebd_memnstr的别名)。对于单个字节,它只调用 memchr 进行线性搜索(因此在 Ο(N) 中)。
但是对于超过一个字节的delimiter值,它会调用memchr在string中搜索delimiter的第一个字节的位置,测试 delimiter 的最后一个字节是否出现在 string 中的预期位置,并调用 memcmp 来检查其间的字节。所以它基本上检查 delimiter 是否包含在 string 中的任何可能位置。这听起来有点像Ο(N2)。
现在让我们看一下该算法的最坏情况,其中模式的第一个和最后一个字节都适合,但倒数第二个不适合,例如:
string: aaaabaaaa
delimiter: aaaaaa
aaaabaaaa
aaaaXa (1+1+5)
aaaX?a (1+1+4)
aaX??a (1+1+3)
aX???a (1+1+2)
X 表示 memcmp 和 ? 未知字节不匹配。括号中的值是统一度量的时间复杂度。这将总结为
Σ (2+i) for i 从 M-floor(N/2) 到 ceil (N/2)
或
(N-M+1)·2 + Σ i - Σ j for i 从 1 到 ceil(N/2), j 从 1 到 M-floor(N/2)-1.
由于 Σ i for i 从 1 到 N 可以表示为 N·( N+1)/2 = (N2+N)/2,我们也可以写成:
(N-M+1)·2 + (ceil(N/2)2 +ceil(N/2))/2 - ((M-floor(N/2)-1)2+(M-floor(N/2)-1))/2
为简单起见,我们假设 N 和 M 总是偶数,所以我们可以省略 'ceil's 和 'floor's:
(N-M+1)·2 + ((N/2+1)2+N/2+1)/2 - ((M-N/2-1)2+(M-N/2)-1)/2
= (N-M+1)·2 + N2/8+3· N/4+1 - ((M-N/2-1)2+(M-N/2)-1)/2
此外,我们可以向上估计值:N-M N和M- N/2-1 N。因此我们得到:
N·2 + N2/8+3·N/4+1 - (N2+N)/2
N·2 + N2+4·N - N2+N
这证明具有多个字节分隔符的explode 在Ο(N2) 中。