我一直试图弄清楚子串算法是什么(在另一个字符串中找到一个字符串)。 PHP使用,我在GitHub上的PHP源代码中找到了以下代码:
我认为它使用的是Bruteforce,但我不确定,这就是为什么我在SO上寻求帮助的原因。
zend_memnstr(const char *haystack, const char *needle, size_t needle_len, const char *end) {
const char *p = haystack;
const char ne = needle[needle_len-1];
ptrdiff_t off_p;
size_t off_s;
if (needle_len == 1) {
return (const char *)memchr(p, *needle, (end-p));
}
off_p = end - haystack;
off_s = (off_p > 0) ? (size_t)off_p : 0;
if (needle_len > off_s) {
return NULL;
}
if (EXPECTED(off_s < 1024 || needle_len < 3)) {
end -= needle_len;
while (p <= end) {
if ((p = (const char *)memchr(p, *needle, (end-p+1))) && ne == p[needle_len-1]) {
if (!memcmp(needle, p, needle_len-1)) {
return p;
}
}
if (p == NULL) {
return NULL;
}
p++;
}
return NULL;
} else {
return zend_memnstr_ex(haystack, needle, needle_len, end);
}
}
答案 0 :(得分:0)
该功能遵循以下步骤:
needle
的最后一个字符加载到ne
,从而在needle_len
为0
时调用未定义的行为。该字节将在稍后的代码中用于通用循环。needle_len == 1
的情况,将搜索委托给标准库函数memchr
。end
指向haystack
之前并在这种情况下返回NULL。这是不一致的,因为只对needle_len != 1
和memchr would be passed a huge length of
end-haystack if
end points before
haystack`执行此一致性检查,可能会调用未定义的行为。1023
或needle_len
小于3
,则该函数会根据memchr
实现一个简单的算法。它扫描needle
的第一个字节,手动检查潜在匹配的最后一个字节,并使用memcmp
验证剩余的潜在匹配。此方法不一致:如果needle_len
为2
,则更简单的扫描将更有效,并且如果所有情况下,由于第一个字节已匹配,应将少一个字节传递给memcmp
。 haystack
长度大于1022且needle
长于2个字节的其他情况,该函数使用zend_memnstr_ex
中实现的另一种方法,nwellnhof
表示是一种变体星期日算法。有关高效字符串搜索的不同方法的更多解释: