zoukankan      html  css  js  c++  java
  • Sunday算法

          Sunday算法是Daniel M.Sunday于1990年提出的字符串模式匹配。其核心思想是:在匹配过程中,模式串发现不匹配时,算法能跳过尽可能多的字符以进行下一步的匹配,从而提高了匹配效率。

      核心思想:在匹配过程中,模式串并不被要求一定要按从左向右进行比较还是从右向左进行比较,它在发现不匹配时,算法能跳过尽可能多的字符以进行下一步的匹配,从而提高了匹配效率。

        算法内容:1.记模式串为S,子串为T,长度分别为N,M。

             2.对于T,我们做一个简单而巧妙的预处理:记录T中每一种字符最后出现的位置,将其存入一个数组中。
             3.假设在发生不匹配时S[i]≠T[j],1≤i≤N,1≤j≤M。设S此次第一个匹配的字符位置为L。显然,S[L+M+1]肯定要参加下一轮的匹配,并且T至少要与S[L+M+1]匹配才有可能与整个S匹配。
             4.这时我们就寻找T中S[L+M+1]出现的位置了。利用我们预处理好的数组,可以O(1)查找出那个位置u,并将其直接移动至T[u]==S[L+M+1]。特殊地,若S[L+M+1]没有在T中出现,那么T不可能会与S[L+M+1]匹配,则将T的第一位直接移动到S[L+M+2],继续匹配。直至L+M>N时,匹配完毕。
              移动步长= 匹配串长度+1

    算法举例

    S:abcceabcaabcd
    T:abcd
    发现d与c不匹配。此时S[L+M+1]=='e',没有出现在T中。于是:
    S:abcceabcaabcd
    T:--------abcd
    发现d与a不匹配。此时S[L+M+1]=='a',T中最后出现在T[0]。于是:
    S:abcceabcaabcd
    T:--------------abcd
    成功匹配。
     
    int wei[301]={0};
    int ans=0,lend,lenc,tot=0;//tot用于统计匹配次数,便于直观地与其他算法比较
    char c[10001],d[10001];
    void pei()
    {
        int w=0;
        while(w+lend<=lenc)
        {
            int i=0;
            bool f=false;
            while(i<=lend && f==false)
            {
                if(c[i+w]!=d[i])f=true;
                i++;tot++;
            }
            if(f==false){ans++;w++;}//ans可以用来记录子串出现的次数
            else
            {
                i=lend+1;
                if(wei[c[i+w]]==-1)w=w+i+1;//不匹配,到下一位
                else w=w+i-wei[c[w+i]];//回到当前这个字符子串的开头
            }
        }
        return;
    }
    int main()
    {
        gets(c);
        gets(d);
        lenc=strlen(c)-1;
        lend=strlen(d)-1;
        for(int i=0;i<=300;++i)wei[i]=-1;
        for(int i=0;i<=lend;++i)
        wei[d[i]]=i;
        pei();
        if(ans)
        cout<<ans<<endl<<tot;
        else cout<<"mission failed";
        return 0;
    }
    

      

    int wei[301]={0};
    int ans=0,lend,lenc,tot=0;
    string c,d;
    void pei()
    {
        int w=0;
        while(w+lend<=lenc)
        {
            int i=0;
            bool f=false;
            while(i<=lend && f==false)
            {
                if(c[i+w]!=d[i])f=true;
                i++;tot++;
            }
            if(f==false){ans++;w++;}
            else
            {
                i=lend+1;
                if(wei[c[i+w]]==-1)w=w+i+1;
                else w=w+i-wei[c[w+i]];
            }
        }
        return;
    }
    int main()
    {
        cin>>c;
        cin>>d;
        lenc=c.length()-1;
        lend=d.length()-1;
        for(int i=0;i<=300;++i)wei[i]=-1;
        for(int i=0;i<=lend;++i)
        wei[d[i]]=i;
        pei();
        if(ans)
        cout<<ans<<endl<<tot;
        else cout<<"mission failed";
        return 0;
    }
    

      ps:以上内容皆整理自百度百科

    我博客里有大量的从别的博客复制过来的代码,分析,以及理解,但我一律会在文章后面标记原博客大佬博客名,其中部分会加以连接。 绝无抄袭的意思,只是为了我在复习的时候找博客方便。 如有原作者对此有不满,请在博客留言,我一定会删除该博文。
  • 相关阅读:
    linux 系统tar文件压缩打包命令
    linux如何查看所有的用户和组信息?
    go语言之行--golang操作redis、mysql大全
    Redis集群的5种使用方式,各自优缺点分析
    docker-compose搭建redis哨兵集群
    windows版 navicat_15.0.18 安装
    redis aof数据持久化
    redis rdb数据持久化
    03.redis 事务
    02 redis 三种特殊的数据类型
  • 原文地址:https://www.cnblogs.com/ZDHYXZ/p/6857788.html
Copyright © 2011-2022 走看看