首页 > 代码库 > HDU 4300 Clairewd’s message(扩展KMP)

HDU 4300 Clairewd’s message(扩展KMP)

思路:extend[i]表示原串以第i开始与模式串的前缀的最长匹配。经过O(n)的枚举,我们可以得到,若extend[i]+i=len且i>=extend[i]时,表示t即为该点之前的串,c即为该点之前的str串,最后输出即可。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
const int N=100010;

char s[N],t[N];
char c[N];
int next[N],extand[N];
void getNext(int lt)
{
    next[0]=lt;
    int a=0;
    while(a<lt-1&&t[a+1]==t[a]) a++;
    next[1]=a;
    a=1;
    for(int k=2;k<lt;k++)
    {
        int p=a+next[a]-1;
        int L=next[k-a];
        if(k-1+L>=p)
        {
            int j=(p-k+1)>0?(p-k+1):0;
            while(j+k<lt&&t[k+j]==t[0+j]) j++;
            next[k]=j;
            a=k;
        }
        else
            next[k]=L;
    }
}

void getExtand(int ls,int lt)
{
    getNext(lt);
    int a=0;
    int minLen=min(ls,lt);
    while(a<minLen&&t[a]==c[a]) a++;
    extand[0]=a;
    a=0;
    for(int k=1;k<ls;k++)
    {
        int p=a+extand[a]-1;
        int L=next[k-a];
        if(k-1+L>=p)
        {
            int j=(p-k+1)>0?(p-k+1):0;
            while(j+k<ls&&j<lt&&t[j+k]==c[j]) j++;
            extand[k]=j;
            a=k;
        }
        else
            extand[k]=L;
    }
}


int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>s>>t;
        map<char,char> mmap;
        int lt=strlen(t);
        int ls=strlen(s);
        for(int i=0;i<ls;i++)
            mmap[s[i]]='a'+i;
        for(int i=0;i<lt;i++)
            c[i]=mmap[t[i]];
        getExtand(lt,lt);
        int i;
        for(i=0;i<lt;i++)
        {
            if(i+extand[i]>=lt&&i>=extand[i])
                break;
        }
        for(int j=0;j<i;j++) cout<<t[j];
        for(int j=0;j<i;j++) cout<<c[j];
        cout<<endl;
    }
    return 0;

}


HDU 4300 Clairewd’s message(扩展KMP)