HDU 2594 (next数组的用法)【KMP】

<题目链接>

题目大意:

给两个字符串,求第一串的前缀与第二串的后缀匹配的最长序列以及长度。

解题分析:

看到这个求前缀和后缀相同序列的最大长度,我们不难想到KMP中的next数组。做法就是, 将这两端序列合并,然后用next数组求出合并后序列的最长前缀后缀相同序列的最大值。但是要注意一点,如果该最大值比a,b字符串序列还要大,说明至少有一个序列的前缀或者后缀延伸到另一个序列了,这明显是不符合题意的,所以,此时我们直接输出最短序列的长度就好了,因为既然能够延伸到另一个序列,那么那个最短的序列一定全部满足,它的前缀或者后缀与另一个序列的后缀或者前缀的相同序列的最大值就是它自身的长度。

#include <cstdio>
#include <cstring>

const int maxn = 50000 + 1000;

char a[maxn << 1], b[maxn];
int Next[maxn << 1];

int min(int a, int b) { return a > b ? b : a; }

void get_next()
{
    int lenn = strlen(a);
    int j = 0, k = -1;
    Next[0] = -1;
    while (j < lenn)
    {
        if (k == -1 || a[j] == a[k])
        {
            Next[++j] = ++k;
        }
        else
            k = Next[k];
    }
}


int main()
{
    while (scanf("%s%s", &a, &b) != EOF)
    {
        int lena = strlen(a);
        int lenb = strlen(b);
        strcat(a, b);
        get_next();     

        int lensum = strlen(a);

        int res = Next[lensum];          //res为合并后序列的前缀和后缀中相同字符串的最长长度
        int len = min(lena, lenb);
        res = min(len, res);       //如果res>lena||res>lenb,直接输出最小的那个就行了
        if (res == 0)
            printf("0\n");
        else
        {
            a[res] = '\0';     //将第res置为'\0',方便输出a的前缀
            printf("%s %d\n", a, res);
        }
    }
    return 0;
}

2018-08-05

猜你喜欢

转载自www.cnblogs.com/00isok/p/9424474.html
今日推荐