sunday算法研究——超越kmp的字符串匹配

第一次听到Sunday算法,是大饼饼说的。在他图文并茂的解释中,我发现这个算法果然是一个又容易理解,效率又强过kmp和BM的算法。

于是试着写了一个,果真是好东东,分享一下。

转一些概念先:

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)。对于短模式串的匹配问题,该算法执行速度较快。
上代码:
int sunday(const char *src,const char *des) { int i,j,pos=0; int len_s,len_d; int next[26]={0}; //next数组,预处理初始化 len_s=strlen(src); len_d=strlen(des); for(j=0;j<26;++j) //初始化next数组 next[j]=len_d; for(j=0;j<len_d;++j) //设置next数组 next[des[j]-'a']=len_d-j; while( pos<(len_s-len_d+1) ) //遍历原串 { i=pos; for(j=0;j<len_d;++j,++i) //比较 { if(src[i]!=des[j]) //一旦不匹配,原串就按照next跳转 { pos+=next[src[pos+len_d]-'a']; break; } } if(j==len_d) return pos; } return -1; //无子串则返回-1 } int main() { char src[]="abcdacdaahfacabcdabcdeaa"; char des[]="abcde"; cout<<sunday(src,des)<<endl; return 0; }

你可能感兴趣的:(算法)