ACM -- 算法小结(五)字符串算法之Sunday算法
1. Sunday算法是Daniel M.Sunday于1990年提出的一种比BM算法搜索速度更快的算法。
2. Sunday算法其实思想跟BM算法很相似,只不过Sunday算法是从前往后匹配,
在匹配失败时关注的是文本串中参加匹配的最末位字符的下一位字符。
如果该字符没有在匹配串中出现则直接跳过,即移动步长= 匹配串长度+ 1;
否则,同BM算法一样其移动步长=匹配串中最右端的该字符到末尾的距离+1。
3. 举例如下:
//pos=0; //匹配串:abcdacdaahfacabcdabcdeaa //模式串:abcde //这里我们看到a-e没有对上,我们就看匹配串中的pos+len2在模式串的位置,然后对齐。 //匹配串:abcdacdaahfacabcdabcdeaa //模式串: abcde //pos=3; //这里我们看到d-a没有对上,我们就看匹配串中的pos+len2在模式串的位置,然后对齐。 //匹配串:abcdacdaahfacabcdabcdeaa //模式串: abcde //pos=8; //这里我们看到h-b没有对上,我们就看匹配串中的pos+len2在模式串的位置,然后对齐。 //匹配串:abcdacdaahfacabcdabcdeaa //模式串: abcde //pos=13; //这里我们看到c-b没有对上,我们就看匹配串中的pos+len2在模式串的位置,然后对齐。 //匹配串:abcdacdaahfacabcdabcdeaa //模式串: abcde //pos=17; //这里我们看到模式串完全匹配
代码演示如下:
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 5 char T[10001]; 6 char P[26]; 7 int next[26]; 8 9 int sunday(const char* T, const char* P) 10 { 11 int len1=strlen(T); 12 int len2=strlen(P); 13 memset(next,0,sizeof(next)); 14 15 for(int j=0; j<26;++j) 16 next[j]=len2+1; 17 for(j=0; j<len2;++j) 18 { 19 next[P[j]-'a']=len2-j; //记录字符到最右段的最短距离+1 20 //cout<<"next["<<P[j]-'a'<<"]="<<next[P[j]-'a']<<endl; 21 } 22 //例如:p[]="abcedfb" 23 //next = {7 6 5 4 3 2 1 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8} 24 25 int pos = 0; 26 while(pos<(len1-len2+1)) //末端对齐 27 { 28 int i=pos; 29 int j; 30 for(j=0;j<len2;++j,++i) 31 { 32 if(T[i]!=P[j]) //不等于就跳跃,跳跃是核心 33 { 34 pos+= next[T[pos + len2]-'a']; 35 //cout<<"pos="<<pos<<endl<<endl; 36 break; 37 } 38 } 39 if(j==len2) 40 return pos; 41 } 42 return -1; 43 } 44 int main() 45 { 46 char T[]="abcdacdaahfacabcdabcdeaa"; 47 char P[]="abcde"; 48 while(scanf("%s%s",T,P)!=EOF) 49 cout<<sunday(T,P)<<endl; 50 return 0; 51 }