关于Sunday算法以及实现

来源:互联网 发布:谷歌版coc数据 编辑:程序博客网 时间:2024/06/04 18:44

今天一早开始学习了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;
}


原创粉丝点击