[英]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-Horspool和Sunday算法。
请参阅原始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 的双向字符串搜索算法的增强版本来解决更大的问题( p
和s
长于 100 和 2100 个字符, s
至少是 6 倍) p
),响应某人报告的病理边缘情况。 添加此更改的提交包括关于算法如何工作的文章。
双向算法的最坏情况时间复杂度为 O(N + M),其中 O(M) 是为从s
搜索针构建移位表而预先支付的成本。 一旦你有了那个表,这个算法确实有 O(N/M) 的最佳性能。
在 python 3.4.2 中,看起来它们使用的是相同的函数,但是时间上可能存在差异。 例如s.find
首先需要查找字符串的find
方法等。
使用的算法是 Boyer-More 和 Horspool 的混合。
我觉得最好的办法就是看源码。 这看起来将实施__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.