PHP使用什么子串算法(找到一个字符串)?

时间:2016-03-13 13:50:20

标签: php c algorithm substring

我一直试图弄清楚子串算法是什么(在另一个字符串中找到一个字符串)。 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);
    }
}

1 个答案:

答案 0 :(得分:0)

该功能遵循以下步骤:

  • 它会将needle的最后一个字符加载到ne,从而在needle_len0时调用未定义的行为。该字节将在稍后的代码中用于通用循环。
  • 特殊情况下needle_len == 1的情况,将搜索委托给标准库函数memchr
  • 它计算要扫描的内存块的长度,允许end指向haystack之前并在这种情况下返回NULL。这是不一致的,因为只对needle_len != 1memchr would be passed a huge length of end-haystack if end points before haystack`执行此一致性检查,可能会调用未定义的行为。
  • 如果长度小于1023needle_len小于3,则该函数会根据memchr实现一个简单的算法。它扫描needle的第一个字节,手动检查潜在匹配的最后一个字节,并使用memcmp验证剩余的潜在匹配。此方法不一致:如果needle_len2,则更简单的扫描将更有效,并且如果所有情况下,由于第一个字节已匹配,应将少一个字节传递给memcmp
  • 对于haystack长度大于1022且needle长于2个字节的其他情况,该函数使用zend_memnstr_ex中实现的另一种方法,nwellnhof表示是一种变体星期日算法。

有关高效字符串搜索的不同方法的更多解释: