HDU 2594 扩展KMP

题目链接

题意:

给两个字符串s1,s2,求s1的前缀和s2的后缀最长相等长度,并将相等部分输出。

思路:

扩展KMP解决的经典问题:定义母串S和子串T,求T与S的每一个后缀的最长公共前缀。

应用到此题将s1作为子串,s2作为母串进行扩展KMP求解,取最长的公共前缀且在s2中为后缀的答案。

C++代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 50010;

int Next[maxn],Ex[maxn];

void GetNext( char *s )
{
    int i=0,j,po,len=strlen(s);
    Next[0] = len;
    while( s[i]==s[i+1]&&i+1<len )
        i++;
    Next[1] = i;
    po = 1;
    for ( i=2 ; i<len ; i++ )
    {
        if ( Next[i-po]+i<Next[po]+po )
            Next[i] = Next[i-po];
        else
        {
            j = Next[po]+po-i;
            if ( j<0 ) j = 0;
            while( i+j<len&&s[j]==s[j+i] )
                j++;
            Next[i] = j;
            po = i;
        }
    }
}

void ExKmp( char *s1 , char *s2 )
{
    int i=0,j,po,len=strlen(s1),l2=strlen(s2);
    GetNext(s2);
    while( s1[i]==s2[i]&&i<l2&&i<len )
        i++;
    Ex[0] = i;
    po = 0;
    for( i=1 ; i<len ; i++ )
    {
        if ( Next[i-po]+i<Ex[po]+po )
            Ex[i] = Next[i-po];
        else
        {
            j = Ex[po]+po-i;
            if ( j<0 ) j = 0;
            while( i+j<len&&j<l2&&s1[i+j]==s2[j] )
                j++;
            Ex[i] = j;
            po = i;
        }
    }
}

char a[maxn],b[maxn];

int main()
{
    while( scanf ( "%s%s" , a , b )==2 )
    {
        int ans = 0,pos = 0,lb = strlen(b);
        ExKmp( b , a );
        for ( int i=0 ; i<lb ; i++ )
        {
            if ( Ex[i]>ans&&i+Ex[i]==lb )
            {
                ans = Ex[i];
                pos = i;
            }
        }
        if ( ans )
        {
            for ( int i=pos ; i<lb ; i++ )
                printf ( "%c" , b[i] );
            printf ( " %d\n" , ans );
        }
        else
            printf ( "%d\n" , ans );
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/game_acm/article/details/80995402
今日推荐