扩展kmp

主要用途
1、主串递减,和模式串比较
从s的i位置开始,i后面的串,和t进行匹配,看最多能匹配多少位(公共前缀)。即为exnext数组

2、模式串和模式串自己的后缀们匹配
t自己,和它的所有后缀们进行匹配,看最大能匹配几个公共前缀,即为next数组(此next数组,对exnext数组有用)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000086;   //字符串长度最大值
int Next[maxn],exnext[maxn]; //ex数组即为extend数组
string s,t;
//预处理计算Next数组
void getnext(string str)           //next[i]表示,t[i...m]与t[1...m]中的最长公共前缀
{
    int i=0,j,po,len=str.size();
    Next[0]=len;//初始化Next[0]
    while(str[i]==str[i+1]&&i+1<len)//计算Next[1]
        i++;
    Next[1]=i;
    po=1;//初始化po的位置
    for(i=2; i<len; i++)
    {
        if(Next[i-po]+i<Next[po]+po)//第一种情况,可以直接得到Next[i]的值
            Next[i]=Next[i-po];
        else//第二种情况,要继续匹配才能得到Next[i]的值
        {
            j=Next[po]+po-i;
            if(j<0)j=0;//如果i>po+Next[po],则要从头开始匹配
            while(i+j<len&&str[j]==str[j+i])//计算Next[i]
                j++;
            Next[i]=j;
            po=i;//更新po的位置
        }
    }
}
//计算extend数组
void exkmp(string s,string t)                    //exnext[i],表示s[i...n]与t[1...m]中的最长公共前缀
{
    int i=0,j,po,len=s.size(),l2=t.size();
    getnext(t);//计算子串的Next数组
    while(s[i]==t[i] && i<l2&&i<len)//计算ex[0]
        i++;
    exnext[0]=i;
    po=0;//初始化po的位置
    for(i=1; i<len; i++)
    {
        if(Next[i-po]+i<exnext[po]+po)//第一种情况,直接可以得到ex[i]的值
            exnext[i]=Next[i-po];
        else//第二种情况,要继续匹配才能得到ex[i]的值
        {
            j=exnext[po]+po-i;
            if(j<0)j=0;//如果i>ex[po]+po则要从头开始匹配
            while(i+j<len&&j<l2&& s[j+i]==t[j])//计算ex[i]
                j++;
            exnext[i]=j;
            po=i;//更新po的位置
        }
    }
}
int main()
{
	//s是主串,不断位移,看看和模式串t能匹配多少位   位移一次,得到一个答案存到exnext数组中
	//t是模式串,它本身和它的后缀进行匹配,看看能匹配多少位
	//结合下面的样例来看吧 
    while(cin>>s>>t)
    {
        exkmp(s,t);
        for(int i=0;i<t.size();i++)
            cout<<Next[i]<<' ';
        
        cout<<endl;
        
        for(int i=0;i<s.size();i++)
            cout<<exnext[i]<<' ';
    }
    return 0;
}


//本代码输出
/*
aaaabaa
aaaaa
5 4 3 2 1
4 3 2 1 0 2 1
*/ 

posted @ 2024-04-19 15:37  涤生yang  阅读(17)  评论(0)    收藏  举报