HDU 2594 Simpsons’ Hidden Talents(拓展Kmp)

传送门

扩展KMP解决的经典问题:定义母串S和子串T,求T与S的每一个后缀的最长公共前缀。应用到此题将s1作为子串,s2作为母串进行扩展KMP求解,取最长的公共前缀且在s2中为后缀的答案。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
void pre_eKmp(char s[],int nt[])
{
    int m = strlen(s);
    nt[0] = m;
    int j = 0;
    while(j + 1 < m && s[j] == s[j + 1])
        j++;
    nt[1] = j;
    int k = 1;
    for(int i = 2;i < m; i++)
    {
        int p = nt[k] + k - 1;
        int l = nt[i - k];
        if(i + l < p + 1)
            nt[i] = l;
        else
        {
            j = max(0,p - i + 1);
            while(i + j < m && s[i + j] == s[j])
                j++;
            nt[i] = j;
            k = i;
        }
    }
}
void eKmp(char x[],int xlen,char y[],int ylen,int nt[],int extend[])
{
    pre_eKmp(x,nt);
    int j = 0;
    while(j < ylen && j < xlen && x[j] == y[j])
        j++;
    extend[0] = j;
    int k = 0;
    for(int i = 1;i < ylen; i++)
    {
        int p = extend[k] + k - 1;
        int l = nt[i - k];
        if(i + l < p + 1)
            extend[i] = l;
        else
        {
            j = max(0,p - i + 1);
            while(i + j < ylen && j < xlen && y[i + j] == x[j])
                j++;
            extend[i] = j;
            k = i;
        }
    }
}
int main()
{
    char s[100050],t[100050];
    int nt[100050],extend[100050];
    memset(extend,0, sizeof(extend));
    memset(nt,0, sizeof(nt));
    while(scanf("%s %s",s,t) == 2)
    {
        eKmp(s,strlen(s),t,strlen(t),nt,extend);
        int ans = 0;
        for(int i = strlen(t) - 1,j = 0;j < strlen(s); j++, i--)
        {
            if(extend[i] == strlen(t) - i)
                ans = max(ans,extend[i]);
        }
        if(ans)
        {
            for(int i =0;i < ans; i++)
                printf("%c",s[i]);
            printf(" ");
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiao__hei__hei/article/details/88621384
今日推荐