Simpsons’ Hidden Talents-(next数组)

Simpsons’ Hidden Talents

 HDU - 2594 

题意前面一堆废话,就是问给出两个字符串s1和s2,问s1的前缀和s2的后缀最大匹配的数量,

这很容易让人想到KMP中求next数组的方法,所以这里可以把s1,s2连接起来,strcat(s1,s2)该函数的作用就是把s2连接到s1的末端

连接完之后就是对串s1进行求next代码详见kMP,接下来就是判断next[k]与len1和len2的关系

如果next[k]大于len1或len2,则继续回溯k=next[k];

这样判断next[k]是否为零,为零则没有匹配,不为零输出next[k]即是最大的匹配数

比如我们已经知道ababab,q=4时,next[4]=2(k=2,表示该字符串的前5个字母组成的子串ababa存在相同的最长前缀和最长后缀的长度是3,所以k=2,next[4]=2。这个结果可以理解成我们自己观察算的,也可以理解成程序自己算的,这不是重点,重点是程序根据目前的结果怎么算next[5]的).,那么对于字符串ababab,我们计算next[5]的时候,此时q=5, k=2(上一步循环结束后的结果)。那么我们需要比较的是str[k+1]和str[q]是否相等,其实就是str[1]和str[5]是否相等!,为啥从k+1比较呢,因为上一次循环中,我们已经保证了str[k]和str[q](注意这个q是上次循环的q)是相等的(这句话自己想想,很容易理解),所以到本次循环,我们直接比较str[k+1]和str[q]是否相等(这个q是本次循环的q)。 
如果相等,那么跳出while(),进入if(),k=k+1,接着next[q]=k。即对于ababab,我们会得出next[5]=3。 这是程序自己算的,和我们观察的是一样的。 
如果不等,我们可以用”ababac“描述这种情况。 不等,进入while()里面,进行k=next[k],这句话是说,在str[k + 1] != str[q]的情况下,我们往前找一个k,使str[k + 1]==str[q],是往前一个一个找呢,还是有更快的找法呢? (一个一个找必然可以,即你把 k = next[k] 换成k- -也是完全能运行的(更正:这句话不对啊,把k=next[k]换成k–是不行的,评论25楼举了个反例)。但是程序给出了一种更快的找法,那就是 k = next[k]。 程序的意思是说,一旦str[k + 1] != str[q],即在后缀里面找不到时,我是可以直接跳过中间一段,跑到前缀里面找,next[k]就是相同的最长前缀和最长后缀的长度。所以,k=next[k]就变成,k=next[2],即k=0。此时再比较str[0+1]和str[5]是否相等,不等,则k=next[0]=-1。跳出循环。 
(这个解释能懂不?)

#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
#define maxn 52025
int nxt[maxn*2];
char str1[maxn*2],str2[maxn];
void getnxt(int len)
{
    int j=-1;
    int i=0;
    nxt[0]=-1;
    while(i<len)
    {
        if(j==-1 || str1[i]==str1[j])
        {
            i++;
            j++;
            nxt[i]=j;
        }
        else
            j=nxt[j];
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    while(~scanf("%s%s",str1,str2))
    {
        int len1=strlen(str1);
        int len2=strlen(str2);
        strcat(str1,str2);
        int len =len1+len2;
        getnxt(len);
        int ans=len;
        while(nxt[ans]>len1||nxt[ans]>len2)
            ans=nxt[ans];
        for(int i=0; i<nxt[ans]; i++)
            printf("%c",str1[i]);
        if(nxt[ans]>0)  printf(" %d\n",nxt[ans]);
        else printf("0\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/BePosit/article/details/81407549