zoukankan      html  css  js  c++  java
  • 扩展KMP

    *算法介绍:

        扩展KMP算法是对KMP算法的一种扩展,对于求两个字符串的公共部分非常有效。题目可以有多种变化。最普通的的是给定母串text与子串part。求数组extend[i],extend[i]表示text[i...n]字符串与part最长前缀的长度。
    *思路:
    1.主代码:
        与KMP的思路一致,我们设next数组表示:next[i...n]与next数组本身的最长公共前缀长度。
        假设我们现在已经知道extend[0....i]的值,接下来要求extend[i+1]的值。设1<=k<=i,且使k+extend[k]最大(这意味着以text[k]为前缀匹配时,在text字符串中匹配达到最远)。
    据extend[k]得:
    text[k...k+extend[k]-1]=part[0...extend[k]-1]
    所以可以推知:
    text[i...k+extend[k]-1]=part[i-k...extend[k]-1]
        根据next数组的意义可以知道以part[i-k]为前缀与part数组的前缀匹配时,匹配长度L=next[i-k]。我们至少可以知道text[i...k+extend[k]-1]与part[0...next[i-k]-1]匹配,长度为L。
       (1)若:L+i
       (2)若:L+i>=k+extend[k] 我们目前只能确定(1)中的L个字符匹配,接下来不能确定,所以需要挨个比较,并且比较完后需令:k=i+1。
    2.next数组的获取:
        与KMP数组的next数组获取思路相同,将以上算法对part字符串自身使用,即可得到。思路分析时只需将上述思路分析中的text字符串替换为part字符串本身,将extend数组替换为next数组即可求得。
    *代码:
    #include<iostream>
    #include<cstring>
    using namespace std;
    int next[1000],lent,lenp,extend[1000];
    char text[1000],part[1000];
    void get_next()
    {
       int j=0,i=0,p,l,k;
       next[0]=lenp;
       while(j<lenp&&part[j]==part[j+1])
        j++;
       next[1]=j;
        k=1;
       for(i=2;i<lenp;i++)
       {
           p=next[k]+k-1,l=next[i-k];
           if(l+i-1<p)
            next[i]=l;
           else
           {
               j=max(0,p+1-i);
               while(i+j<lenp&&part[j]==part[i+j])
                j++;
               next[i]=j;
               k=i;
           }
       }
    }
    int extend_KMP()
    {
        int i,j=0,l,k=0,p;
        get_next();
        while(j<lent&&j<lenp&&part[j]==text[j])
            j++;
        extend[0]=j;
        for(i=1;i<lent;i++)
        {
            l=next[i-k];
            p=extend[k]+k-1;
            if(l+i-1<p)
                extend[i]=l;
            else
            {
                j=max(0,p+1-i);
                while(j+i<lent&&part[j]==text[i+j])
                    j++;
                extend[i]=j;
                k=i;
            }
        }
    }
    int main()
    {
        int i;
       cin>>part>>text;
       lenp=strlen(part);
       lent=strlen(text);
       extend_KMP();
       for(i=0;i<lenp;i++)
        cout<<next[i];
       cout<<endl;
       for(i=0;i<lent;i++)
       cout<<extend[i];
       return 0;
    }
  • 相关阅读:
    C字符串和C++字符串
    Linux的用户态和内核态
    知乎问答:如何理解“In UNIX, everything is a file”?
    科普:并行计算、分布式计算、集群计算和云计算
    个人使用VIM的一些总结
    C语言回调函数学习
    Python的函数参数传递:传值?引用?
    ECMAScript 函数函数概述
    ECMAScript 函数arguments 对象
    ECMAScript 语句with 语句
  • 原文地址:https://www.cnblogs.com/Neptunes/p/3304257.html
Copyright © 2011-2022 走看看