一种可做特殊用途的字符串匹配算法
纪福全 朱战立
(西安石油大学计算机学院,西安 710065)
摘 要 现有的字符串匹配算法按照模式串从左至右或从右至左的顺序匹配,都是直接进行比较,本文提出了一种可做特殊用途的字符串匹配算法——ZZL算法。对于频繁使用的要匹配的主串和模式串来说,ZZL算法的匹配速度会非常快。
关键词 字符串,模式匹配,算法
字符串匹配就是在一个字符串中查找模式串的一个或所有出现。字符串匹配用途很广泛。例如,在拼写检查、语言翻译、数据压缩、搜索引擎、网络入侵检测、计算机病毒特征码匹配以及DNA序列匹配等应用中,都需要进行字符串匹配。已经提出了许多字符串匹配算法。传统的有BF算法[2,3]、KMP算法[2,3]等,最近提出的有BM算法[2,4]、Sunday算法[2,3]等。本文提出一种可做特殊用途的字符串匹配算法——ZZL算法。
1 相关算法分析
字符串模式匹配的含义是:在主串S中,从位置start开始查找是否存在模式串(也称作模式串)T,如在主串S中查找到一个与模式串T相同的模式串,则模式串与主串匹配;如在主串S中未查找到一个与模式串T相同的模式串,则不匹配 [1] 。
首先作如下假设:
主串S:S[1…N],长度为N;模式串T:T[1…M],长度为M;N≥M;
1.1 BF算法
BF(Brute Force)算法核心思想是:首先S[1]和T[1]比较,若相等,则再比较S[2]和T[2],一直到T[M]为止;若S[1]和P[1]不等,则T向右移动一个字符的位置,再依次进行比较。如果存在k,1≤k≤N,且S[k+1…k+M]=T[1…M],则匹配成功;否则失败。该算法最坏情况下要进行M*(N-M+1)次比较,时间复杂度为O(M*N)。
1.2 KMP算法
KMP(Knuth-Morris-Pratt)算法核心思想是:在发生失配时,主串不需要回溯,而是利用已经得到的“部分匹配”结果将模式串右移尽可能远的距离,继续进行比较。这里要强调的是,模式串不一定向右移动一个字符的位置,右移也不一定必须从模式串起点处重新试匹配,即模式串一次可以右移多个字符的位置,右移后可以从模式串起点后的某处开始试匹配。
假设发生失配时,S[i]≠T[j],1≤i≤N,1≤j≤M。则下一轮比较时,S[i]应与T[next[j]]对齐往后比较:
如T=“abaabcac”,则
1.3 BM算法
对于给出的长度为m的模式串T=T&&05;···Tm和主串S=S&&05;···Sn,实现BM算法需要一个辅助数组bm[ ]。它用字符值作为数组的下标,数组的大小依赖于可能出现的字符多少,与模式串的大小无关。对于需要进行中文关键字的匹配,需要扩充ASCII字符集,数组大小则为256。对于任意x属于集合Σ→{1,2,···,256},bm[x]的值为:
该数组每个字符对应的项记录着该字符在模式串中最后一次出现的位置。
BM算法思想是:假如在执行主串位置i起“返前”的一段与模式串T从右向左的字符匹配中,如果模式串T全部字符匹配,则匹配成功;否则需要右移,开始新的一轮匹配,假设匹配不成功发生在模式串中的位置j,由主串匹配不成功字符Si-m+j查找辅助数组得到该字符在模式串T中的最后出现的位置值bm[Si-m+j]。如果bm[Si-m+j]等于零,表示字符Si-m+j不在模式串T中,则模式串跳过该字符,在该字符下一个位置对齐;如果bm[Si-m+j]大于j,表示这个字符在模式串中最后出现的位置在j的左边,则模式串T右移对齐字符Si-m+j;如果bm[Si-m+j]小于j,表示这个字符在模式串中最后出现的位置在j的右边,模式串不能左移,就右移一格。移动量为shift=max(1,m-bm[i-m+j])。
1.4 Sunday算法
Sunday算法是Daniel M.Sunday于1990年提出的一种比BM算法搜索速度更快的算法。其核心思想是:在匹配过程中,模式串并不被要求一定要按从左向右进行比较还是从右向左进行比较,它在发现不匹配时,算法能跳过尽可能多的字符以进行下一步的匹配,从而提高了匹配效率。
假设在发生不匹配时S[i]≠T[j],1≤i≤N,1≤j≤M。此时已经匹配的部分为u,并假设字符串u的长度为L。如图1。明显的,S[L+i+1]肯定要参加下一轮的匹配,并且T[M]至少要移动到这个位置(即模式串T至少向右移动一个字符的位置)。
图1 Sunday算法不匹配的情况
分如下两种情况:
(1) S[L+i+1]在模式串T中没有出现。这个时候模式串T[0]移动到S[T+i+1]之后的字符的位置。如图2。
图2 Sunday算法移动的第1种情况
(2)S[L+i+1]在模式串中出现。这里S[L+i+1]从模式串T的右侧,即按T[M-1]、T[M-2]、…T[0]的次序查找。如果发现S[L+i+1]和T中的某个字符相同,则记下这个位置,记为k,1≤k≤M,且T[k]=S[L+i+1]。此时,应该把模式串T向右移动M-k个字符的位置,即移动到T[k]和S[L+i+1]对齐的位置。如图3。
图3 Sunday算法移动的第2种情况
依次类推,如果完全匹配了,则匹配成功;否则,再进行下一轮的移动,直到主串S的最右端结束。该算法最坏情况下的时间复杂度为O(N*M)。对于短模式串的匹配问题,该算法执行速度较快。
2 ZZL算法
现有的字符串匹配算法不论是按照模式串从左至右还是从右至左的顺序匹配,都是直接进行比较,而ZZL算法的核心思想是:首先在主串S中查找模式串T的首字母,每找到一个则将它的位置存储,然后依次提取这些位置,从这些位置开始继续匹配模式串T。对于频繁使用的要匹配的主串和模式串来说,由于预先保存了模式串在主串中的所有存储位置,所以匹配速度会非常快。
2.1 预处理
预处理主要完成查找模式串首字符在主串中的所有出现位置,并将其保存在一个数组中。
查找模式串首字符算法如下:
k=0;
for(i=start;i<S.length-T.length;i++)
{
if(S.str[i]==T.str[0])
{
x[k]=i;
k++; // k为模式串首字母在主串中出现的次数
}
}
2.2 匹配
在预处理的基础上,字符串匹配算法就可以从查找到的模式串在主串中的位置开始,匹配模式串首字母之后的其余部分。此时,采用BF算法即可,并可设置一个计数器,记录匹配次数。
匹配算法如下:
v=0;
for(m=0;m<k;m++)
{
for(j=1;j<T.length;j++)
{
if(S.str[x[m]+1]==T.str[j])
{
v++;
x[m]++;
}
else
{
v++;
break;
}
}
}
3 算法性能分析及实验结果分析
3.1 算法性能分析
如果不考虑算法的预处理过程,若模式串首字母在主串中出现k次,则ZZL算法最坏情况下比较次数为k*(M-1)<k*M。如果考虑算法的预处理过程,则总的比较次数需再加上N次,即为k*M+N。
3.2 实验结果
为了评测该算法的性能,随机的抽取一段文本和模式串,并在同一台计算机上用不同的算法进行匹配。测试文本主串S="From automated teller machines and atomic clocks to mammograms and semiconductors,innumerable products and services rely in some way on technology,measurement,and standards provided by the National Institute of Standards and Technology",模式串T="products and services"。分别用BF算法、KMP算法、BM算法、Sunday算法和ZZL算法在同一台计算机上进行匹配计算,并统计每种算法匹配时总的字符匹配次数。测试结果如表1。
表1 匹配算法实验结果
算法
|
BF
|
KMP
|
BM
|
Sunday
|
ZZL
|
一次匹配的总的字
符匹配次数
|
116
|
95
|
108
|
110
|
23
|
4 结论
对于频繁使用的要匹配的主串和模式串来说,由于预先保存了模式串在主串中的所有存储位置,所以ZZL算法的匹配速度会非常快。
参考文献:
1 朱战立编著. 数据结构——使用C语言(第3版)[M]. 西安:西安交通大学出版社,2004
2 王成,刘金刚. 一种改进的字符串匹配算法[J]. 计算机工程,2006,32(2):62-64
3 Christian Charras, Thierry Lecroq. Exact String Matching Algorithms[Z]. http://www-igm.univmlv.fr/~lecroq/string/
4黄中清,汪文勇,黄鹂声. 基于WinPcap和改进的BM算法的网络信息审计系统的实现[Z].
收稿日期:3月17日
修改日期:4月1日
作者简介:纪福全(1981-),男,硕士生,主研方向:人工智能与专家系统,神经网络;
朱战立,教授、硕导
原理挺简单的。不知道真的效果怎么样?