一直以为strstr效率很不错,今天看了一下代码,被震撼到了。。
先贴一个注释:
/* Return the first location of non-empty NEEDLE within HAYSTACK, or
NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This
method is optimized for LONG_NEEDLE_THRESHOLD <= NEEDLE_LEN.
Performance is guaranteed to be linear, with an initialization cost
of 3 * NEEDLE_LEN + (1 << CHAR_BIT) operations.
If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at
most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching,
and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible.
If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and
sublinear performance is not possible. */
这是函数
static RETURN_TYPE
two_way_long_needle (const unsigned char *haystack, size_t haystack_len,
const unsigned char *needle, size_t needle_len)
的一段注释。
haystack是主串,needle是模式串,注释中的红色表示:每次查找都要耗费3 * len(T) + 256的时间来初始化!!
难怪为什么我的这么慢。。原来是每次都初始化去了。。极度无语中。。
至于C++ string的find嘛,复杂度我分析不出来。。看源代码看了N久就再也没耐心去看了。。
贴一下吧。。
首先是string的引用:(以下就是<string>的除去注释与宏外的全部内容)
#include <bits/c++config.h>
#include <bits/stringfwd.h>
#include <bits/char_traits.h> // NB: In turn includes stl_algobase.h
#include <bits/allocator.h>
#include <bits/cpp_type_traits.h>
#include <bits/localefwd.h> // For operators >>, <<, and getline.
#include <bits/ostream_insert.h>
#include <bits/stl_iterator_base_types.h>
#include <bits/stl_iterator_base_funcs.h>
#include <bits/stl_iterator.h>
#include <bits/stl_function.h> // For less
#include <ext/numeric_traits.h>
#include <bits/stl_algobase.h>
#include <bits/basic_string.h>
#ifndef _GLIBCXX_EXPORT_TEMPLATE
# include <bits/basic_string.tcc>
#endif
主要过程全部实现在<bits/basic_string.h>里
再给出basic_string.h里的一段程序
/**
* @brief Find position of a C substring.
* @param s C string to locate.
* @param pos Index of character to search from.
* @param n Number of characters from @a s to search for.
* @return Index of start of first occurrence.
*
* Starting from @a pos, searches forward for the first @a n characters
* in @a s within this string. If found, returns the index where it
* begins. If not found, returns npos.
*/
size_type
find(const _CharT* __s, size_type __pos, size_type __n) const;
/**
* @brief Find position of a string.
* @param str String to locate.
* @param pos Index of character to search from (default 0).
* @return Index of start of first occurrence.
*
* Starting from @a pos, searches forward for value of @a str within
* this string. If found, returns the index where it begins. If not
* found, returns npos.
*/
size_type
find(const basic_string& __str, size_type __pos = 0) const
{ return this->find(__str.data(), __pos, __str.size()); }
find这个主函数的代码在这里没写出来。不过没关系,还有stl的source呢。。
在SGI中,又看到了这段函数:
template <class _CharT, class _Traits, class _Alloc>
basic_string<_CharT,_Traits,_Alloc>::size_type
basic_string<_CharT,_Traits,_Alloc>
::find(const _CharT* __s, size_type __pos, size_type __n) const
{
if (__pos + __n > size())
return npos;
else {
const const_iterator __result =
search(_M_start + __pos, _M_finish,
__s, __s + __n, _Eq_traits<_Traits>());
return __result != _M_finish ? __result - begin() : npos;
}
}
又是调用search。。search在那里捏?我来search一下。。
答案是在<stl_algo.h>里。。
最后,贴一贴search的实现。。说实话,看了半天没看懂。。
template <class _ForwardIter1, class _ForwardIter2, class _BinaryPred>
_ForwardIter1 search(_ForwardIter1 __first1, _ForwardIter1 __last1,
_ForwardIter2 __first2, _ForwardIter2 __last2,
_BinaryPred __predicate)
{
__STL_REQUIRES(_ForwardIter1, _ForwardIterator);
__STL_REQUIRES(_ForwardIter2, _ForwardIterator);
__STL_BINARY_FUNCTION_CHECK(_BinaryPred, bool,
typename iterator_traits<_ForwardIter1>::value_type,
typename iterator_traits<_ForwardIter2>::value_type);
// Test for empty ranges
if (__first1 == __last1 || __first2 == __last2)
return __first1;
// Test for a pattern of length 1.
_ForwardIter2 __tmp(__first2);
++__tmp;
if (__tmp == __last2) {
while (__first1 != __last1 && !__predicate(*__first1, *__first2))
++__first1;
return __first1;
}
// General case.
_ForwardIter2 __p1, __p;
__p1 = __first2; ++__p1;
_ForwardIter1 __current = __first1;
while (__first1 != __last1) {
while (__first1 != __last1) {
if (__predicate(*__first1, *__first2))
break;
++__first1;
}
while (__first1 != __last1 && !__predicate(*__first1, *__first2))
++__first1;
if (__first1 == __last1)
return __last1;
__p = __p1;
__current = __first1;
if (++__current == __last1) return __last1;
while (__predicate(*__current, *__p)) {
if (++__p == __last2)
return __first1;
if (++__current == __last1)
return __last1;
}
++__first1;
}
return __first1;
}
有哪位大牛看懂了能否分析一下时间复杂度???膜拜!!!