字符串匹配Sunday算法
sunday算法简介
Sunday算法是Daniel M.Sunday于1990年提出的一种比BM算法搜索速度更快的算法。其核心思想是:在匹配过程中,模式串并不被要求一定要按从左向右进行比较还是从右向左进行比较,它在发现不匹配时,算法能跳过尽可能多的字符以进行下一步的匹配,从而提高了匹配效率(算法思想很简单)。在一定程度上比KMP算法和BM算法更优。但是该算法最坏情况下的时间复杂度为O(m*n)。
Sunday的算法思想和Horspool有些相似,但是。当出现不匹配的时候,却不是去找匹配串中不匹配的字符在模式串的位置,而是直接找最右边对齐的右一位的那个字符在模式串的位置。
sunday算法原理
举个栗子:设字符串为 THIS IS A SIMPLE EXAMPLE,搜索词为EXAMPLE如图所示。
1.
第一次匹配过程中,从搜索词的首字母开始从左往右匹配,字符串中的“H”与 “E”发现不匹配,就查找字符串中右端对齐的字符的下一位,也就是“ ”(空格),原则:如果该字符没有在匹配串中出现则直接跳过,即移动步长= 匹配串长度+1;否则,同BM算法一样其移动步长=匹配串中最右端的该字符到末尾的距离+1。
2.
发现字符串与搜索词右端对齐的下一位字符即“ ”(空格)并不在搜索词中出现过,就移动步长为8位,如图所示。
3.
继续从左往右开始匹配字符,发现字符串中的“A”与搜索词中的“E”并不匹配,就查看右端对齐的下一个字符“E”,发现“E”在搜索词中,并且有两个,按照suanday原则就选择搜索词中最右的字符“E”,这样可以保证在右端对齐的下以一个字符在搜索词中存在的情况下,移动步长最小,保证这种情况下不失匹配机会。
移动后,从左往右开始匹配,发现是“ ”(空格)与搜索词的首字母“E”不匹配,继续按上述匹配原则进行移动。
4.
字符串与搜索词最右端的下一个字符是“ ”(空格),依照上述原则,在搜索词中并不存在“ ”(空格),移动的步长为8,最终结果如图所示。
Sunday算法C语言实现
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef int status;
#define MAXSIZE 100
#define ERROR 0
#define TRUE 1
//初始化数据
status InitData(char **source,char **target){
char ch;
int i = 0;
(*source) = (char *)malloc(sizeof(char) * MAXSIZE);
(*target) = (char *)malloc(sizeof(char) *MAXSIZE);
if((*source)==NULL || (*target) ==NULL){
printf("初始化错误...");
return ERROR;
}
//输入字符串
printf("请输入字符串,以#结束\n");
while((ch = getchar())!='#'){
(*source)[i++] = ch;
(*source)[i] = '\0';
}
getchar(); //清除缓冲区回车键
i = 0; //重置
printf("请输入搜索词,以#结束\n");
while((ch = getchar()) !='#'){
(*target)[i++] = ch;
(*target)[i]='\0';
}
}
//找出temp在target的位置
int FindIndex(char *target,char temp){
int i= 0;
if(target ==NULL){
printf("搜索词为空...");
exit(-1); //异常退出
}
for(i = strlen(target) -1;i>=0;i--){
if(target[i] == temp){
return i;
}
}
return -1; //未找到字符匹配位置
}
//sunday算法
status Sunday(char *source,char *target){
int i= 0,j = 0,srclen = strlen(source),tarlen=strlen(target);
int temp =0,index = -1;
if(source ==NULL || target ==NULL){
printf("请初始化...\n");
return ERROR;
}
while(i<srclen){ //循环条件
if(source[i] == target[j]){
if(j==tarlen-1){
printf("匹配成功...");
return TRUE;
}
i++;j++;
}else{ //发现不相等位置
temp = tarlen - j + i; //字符串后面的第一个字符位置
index = FindIndex(target,source[temp]);
if(index==-1){ //未找到位置,后移
i = temp+1;
j = 0;
}else{ //找到位置
i = temp-index;
j = 0;
}
}
}
printf("匹配失败..");
return ERROR;
}
void main(){
char *source,*target;
InitData(&source,&target);
Sunday(source,target);
}