有大量的字符串搜索算法在http://www-igm.univ-mlv.fr/~lecroq/string/了廣泛的討論,說明C代碼和引用。
有一組關於該算法的成本意見的討論。需要牢記的一點是,如果您可以通過搜索功能的多次調用分攤安裝成本,那麼高性能算法可以爲您帶來巨大收益。如果你一直在尋找不同的絃樂,那麼贏得比賽就會變得更加困難。
我有一個KMP版本(Knuth-Morris-Pratt)算法打包,用於多次重複使用相同的搜索字符串。標題是:
/*
@(#)File: $RCSfile: kmp.h,v $
@(#)Version: $Revision: 1.4 $
@(#)Last changed: $Date: 2008/02/02 05:49:34 $
@(#)Purpose: Knuth-Morris-Pratt Search Algorithm
@(#)Author: J Leffler
@(#)Copyright: (C) JLSS 2005,2008
@(#)Product: :PRODUCT:
*/
#ifndef KMP_H
#define KMP_H
#include <stddef.h> /* size_t */
typedef struct kmp_control kmp_control;
/*
** To set up a search (to repeatedly look for the same search string in
** multiple scan strings), use kmp_setsearch(). To start a search on a
** new scan string, use kmp_settarget(). To find the next match of a
** given search string in a given target string, use kmp_search(). Note
** that kmp_setsearch() and kmp_settarget() do not copy the data in the
** source and target strings; the pointers must remain valid You can
** copy kmp_control structures for reuse if desired.
*/
typedef void *(*kmp_malloc)(size_t nbytes);
typedef void (*kmp_free)(void *data);
extern kmp_control *kmp_setsearch(const char *search, size_t schlen);
extern void kmp_settarget(kmp_control *ctrl, const char *target, size_t tgtlen);
extern const char *kmp_search(kmp_control *ctrl);
extern void kmp_release(kmp_control *ctrl);
extern void kmp_setalloc(kmp_malloc mem_alloc, kmp_free mem_free);
#endif /* KMP_H */
能夠指定內存分配函數是一點點不尋常的 - 但我的代碼通常工作在內存分配不是通過標準malloc()
完成等的環境,你必須能夠按需切換內存分配器。您可以忽略兩個typedef和相應的函數;當然,默認設置是使用malloc()
和free()
。
基本KMP算法的代碼來自上方部位 - 但進行了修改,允許我設置搜索字符串一次,然後搜索多個目標串等聯繫我(見我的個人資料)的源代碼。我也得到了Boyer-Moore代碼的類似結構(相同的原始源代碼),以及不區分大小寫的Boyer-Moore代碼。
關於strstr()
有一個很好的戰爭故事,並在Kernighan和派克的優秀書籍「The Practice of Programming」中表現出色。
我做了一些實驗 - 利用國王詹姆斯聖經(4.8 MB)的副本作爲純文本,並且內存映射這一點。對於許多搜索,(MacOS X 10.6.2/BSD)strstr()
比KMP或BM更快。當琴絃長得足夠長時(大約12個以上的字符),則BM算法最終超過了strstr()
。 KMP算法似乎總是比較慢很多。
道德?
- 很難超出一個好的圖書館。
- 在合理的英文字符串上,KMP比BM慢得多。
而我在這些算法周圍放置的基礎設施可能太重了 - 但原始代碼中的替代方法是回調機制,它在確定匹配上下文時存在一些問題。
而且,的strstr()是POSIX - 是啊! http://www.opengroup.org/onlinepubs/9699919799/ – 2010-03-27 20:19:05
@Kevin:不在C標準庫中,它的意思是它也在POSIX中? (POSIX規定,其目標之一是 「與ISO/IEC 9899對齊:1999標準,包括ISO/IEC 9899:1999/Cor.2:2004(E)」) – 2010-03-27 21:21:57
@邁克爾:我認爲你是正確的,在至少就「string.h」的內容而言。我只是試圖強化Jefromi輕輕推動的「*標準*庫功能」概念,爲POSIX帶來歡呼,這是一個20年以上的習慣,難以打破! :) – 2010-03-27 23:28:58