今天一早开始学习了Sunday算法。比BM算法要简单易懂,而且网上也说了这个效率比BM还要高(具体怎么样我不知道,没有测试过)。
Sunday算法是Daniel M.Sunday于1990年提出的一种比BM算法搜索速度更快的算法。
string: d g j h o l p k j h s i j w a v n m..........
pattern: j h h i
如上,我们匹配串是j h s i。比较pattern与string。如果匹配则好,不匹配的话,我们的关注目标就是string里面的下一个字符,也就是o这个位置的字符,因为无论如何我们都会至少向后移动一位。
sunday算法核心就是看string里面与pattern对比后的下一个字符。
第一种情况如这个字符不在pattern里面的话,我们可以直接跳过,因为不可能会与pattern不包含的字符相匹配。这时候就变成这样:
string: d g j h o l p k j h s i j w a v n m..........
pattern: j h h i
第二种情况:这个字符在pattern里面,我们就把最右边的那个匹配的字符与其对齐:
string: d g j h o l p k j h s i j w a v n m..........
pattern: j h h i
就这样一直循环这个步骤,一直到找到或则找不到,返回结果。
整个过程就是以下一个字符在pattern里面或则不在pattern里面来划分的。这样应该很能理解。
我的代码主要分为3个模块:
1、int comparePatternAndString(char *pattern,int plen,char *str,int currentLocationInString)
主要是用来比较pattern与string中对应的字符串是否相等,若相等就返回1,否则返回0.
2、int IsinthePattern(char a,char *pattern,int plen)
判断后一个字符是否在pattern中,若在,返回它的位置,若不在,返回0.
3、main函数。
整体代码如下:
// sunday1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
using namespace std;
int comparePatternAndString(char *pattern,int plen,char *str,int currentLocationInString)
{
int i=plen-1;
int j=currentLocationInString;
int tag=1;//标识符,如果有一个不匹配,tag为0.
while(i>=0 && tag==1)
{
if(pattern[i]!=str[j])
tag=0;
i--;
j--;
}
return tag;//tag=1表示成功,否则失败。
}
int IsinthePattern(char a,char *pattern,int plen)
{
int i=plen-1;
int tag=0;
while(i>=0 && tag==0)
{
if(pattern[i]==a)
tag=1;
i--;
}
if(tag==1)
return i+1;//若在pattern中,返回最右边的匹配的位置。
else
return 0;//没有匹配,就返回0
}
int _tmain(int argc, _TCHAR* argv[])
{
char *string1="fgjsderiodfda1546egdjkjdkfdadghh";
char *pattern="fda";
int start=0,find=0,in=0,tag=1;
int currentPosition=0;
int length,plen;
plen=strlen(pattern);
currentPosition=plen-1;//目前对齐后的最后一个下标。
length=strlen(string1);
if(plen>length)
{
cout<<"the pattern is longer than string,we can not compare."<<endl;
}
//tag用来标识是否应该结束。匹配成功与否还是要看find。
while(tag==1)
{
find=comparePatternAndString(pattern,plen,string1,currentPosition);
//若不匹配
if(find==0)
{
//找到末尾了没有找到。
if(currentPosition+1==length)
{
tag = 0;
}
//还没有到末尾
else
{
in=IsinthePattern(string1[currentPosition+1],pattern,plen);
//没有在pattern里面,跳过。
if(in==0)
{
//后面的不足plen位,找不到了。
if(currentPosition+1+plen>length)
{
tag = 0;
}
else
{
currentPosition=currentPosition+1+plen;//重定位currentPosition
}
}//if(in==0)
//这个字符在pattern里面
else
{
currentPosition=currentPosition+plen-in;
}
}
}//if(find==0)
else
tag=0;
}//while
if(find==0)
cout<<"there is no pattern in the string."<<endl;
if(find==1)
cout<<"there is a pattern in the string.and the position is "<<currentPosition-plen+1<<endl;
return 0;
}