高速字符串匹配 zzl算法
这个大概我这段时间稍微有点成就感的东西了。
学了数据结构,但是编写代码的时候还是照着书抄,没有一点意思……
字符串匹配在补丁的时候是非常有用的。
之前我用的普通方法查找,就是一个一个的往前。搜索一个300kb的文件大概需要4秒时间。
看了ZZL算法原理以后,自己就编写了出来。查找这个相同的文件,需时约0.4秒。
大家能够感觉到差距吧?整整10倍啊!
算法思想大意是每次能够尽量多的移动匹配位置,因此建立一个开始匹配的索引。
整个程序需要两部
预处理
预处理主要完成查找模式串首字符在主串中的所有出现位置,并将其保存在一个数组中。
查找模式串首字符算法如下:
k=0;
for(i=start;i<S.length-T.length;i++)
{
if(S.str[i]==T.str[0])
{
x[k]=i;
k++; // k为模式串首字母在主串中出现的次数
}
}
匹配
在预处理的基础上,字符串匹配算法就可以从查找到的模式串在主串中的位置开始,匹配模式串首字母之后的其余部分。此时,采用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;
}
}
}
算法性能分析
如果不考虑算法的预处理过程,若模式串首字母在主串中出现k次,则ZZL算法最坏情况下比较次数为k*(M-1)
如果考虑算法的预处理过程,则总的比较次数需再加上N次,即为k*M+N。
最后,我把我实现的算法写出来吧,可不是伪代码哦,保证能够编译通过的。
//www.shuax.com
//舒俊杰 2009.11.29
#include <stdio.h>
#include <stdlib.h>
int main()
{
int key[] = {0x74, 0x07, 0xB8, 0x04, 0x40, 0x00, 0x80, 0xEB, 0x0F};
FILE *fp;
fp = fopen("XLUser.dll", "rb");
fseek(fp, 0L, 2);
long filelen = ftell(fp);//为了加快速度,可自定义文件长度
long feature = 0;
long point;
//索引顺序表
int length = 200;
long *seek = (long *)malloc(length * sizeof(long));
int i = 0;
int j = 0;
//建立索引,我自己改进了一下ZZL
//既然可以查询首字符,那么一次查询两个也行吧?
fseek(fp, 0L, 0);
while (ftell(fp) < filelen )
{
if (fgetc(fp) == key[0] && fgetc(fp) == key[1])
{
feature++;
if (feature == length)
{
seek = (long *)realloc(seek, (length + 40) * sizeof(long));
length += 40;
}
seek[feature] = ftell(fp);
}
}
//根据索引查找
for (i = 0;i < feature;i++)
{
fseek(fp, seek[i], 0);
for (j = 2; j < 9;j++)
{
if (fgetc(fp) != key[j]) break;
}
if (j > 8) point = ftell(fp);
}
fclose(fp);
printf("%x", point);
return 0;
}
这个就是我的迅雷补丁的核心算法啦…自我感觉良好…哈哈
实验结果
为 了评测该算法的性能,随机的抽取一段文本和模式串,并在同一台计算机上用不同的算法进行匹配。测试文本主串S=”Fromautomated teller machines and atomic clocks to mammograms andsemiconductors,innumerable products and services rely in some way ontechnology,measurement,and standards provided by the National Instituteof Standards and Technology”,模式串T=”products andservices”。分别用BF算法、KMP算法、BM算法、Sunday算法和ZZL算法在同一台计算机上进行匹配计算,并统计每种算法匹配时总 的字符匹配次数。测试结果:
算法 BF KMP BM Sunday ZZL
一次匹配的总的字
符匹配次数 116 95 108 110 23
转:http://www.shuax.com/?p=871