繁体   English   中英

python的if子串在字符串中的运行时

[英]Runtime of python's if substring in string

以下if statement的大 O 是什么?

if "pl" in "apple":
   ...

python如何确定字符串“pl”是否在字符串“apple”中找到的整体大O是什么

或字符串搜索中的任何其他子字符串。

这是测试子字符串是否在字符串中的最有效方法吗? 它是否使用与.find()相同的算法?

时间复杂度平均为 O(N),最坏情况为 O(NM)(N 是较长字符串的长度,M 是您搜索的较短字符串)。 从 Python 3.10 开始,启发式用于通过切换算法将最坏情况降低到 O(N + M)。

相同的算法用于str.index()str.find()str.__contains__()in运算符)和str.replace() 它是Boyer-Moore的简化,其思想取自Boyer-Moore-HorspoolSunday算法。

请参阅原始stringlib讨论帖子,以及fastsearch.h源代码 在 Python 3.10 之前,自Python 2.5 引入以来,基本算法没有改变(除了一些低级优化和极端情况修复)。

该帖子包括该算法的 Python 代码大纲:

 def find(s, p): # find first occurrence of p in s n = len(s) m = len(p) skip = delta1(p)[p[m-1]] i = 0 while i <= nm: if s[i+m-1] == p[m-1]: # (boyer-moore) # potential match if s[i:i+m-1] == p[:m-1]: return i if s[i+m] not in p: i = i + m + 1 # (sunday) else: i = i + skip # (horspool) else: # skip if s[i+m] not in p: i = i + m + 1 # (sunday) else: i = i + 1 return -1 # not found

以及速度比较。

在 Python 3.10 中,算法更新为使用Crochemore 和 Perrin 的双向字符串搜索算法的增强版本来解决更大的问题( ps长于 100 和 2100 个字符, s至少是 6 倍) p ),响应某人报告病理边缘情况 添加此更改的提交包括关于算法如何工作的文章

双向算法的最坏情况时间复杂度为 O(N + M),其中 O(M) 是为从s搜索针构建移位表而预先支付的成本。 一旦你有了那个表,这个算法确实有 O(N/M) 的最佳性能。

在 python 3.4.2 中,看起来它们使用的是相同的函数,但是时间上可能存在差异。 例如s.find首先需要查找字符串的find方法等。

使用的算法是 Boyer-More 和 Horspool 的混合。

您可以使用timeittimeit测试:

maroun@DQHCPY1:~$ python -m timeit 's = "apple";s.find("pl")'
10000000 loops, best of 3: 0.125 usec per loop
maroun@DQHCPY1:~$ python -m timeit 's = "apple";"pl" in s'
10000000 loops, best of 3: 0.0371 usec per loop

使用in确实更快(0.0371 usec 与 0.125 usec 相比)。

对于实际实现,您可以查看代码本身

我觉得最好的办法就是看源码。 看起来将实施__contains__

static int
bytes_contains(PyObject *self, PyObject *arg)
{
    Py_ssize_t ival = PyNumber_AsSsize_t(arg, PyExc_ValueError);
    if (ival == -1 && PyErr_Occurred()) {
        Py_buffer varg;
        Py_ssize_t pos;
        PyErr_Clear();
        if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
            return -1;
        pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self),
                             varg.buf, varg.len, 0);
        PyBuffer_Release(&varg);
        return pos >= 0;
    }
    if (ival < 0 || ival >= 256) {
        PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
        return -1;
    }

    return memchr(PyBytes_AS_STRING(self), (int) ival, Py_SIZE(self)) != NULL;
}

在以下方面stringlib_find()它使用fastsearch()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM