hdu 1867 A + B for you again (kmp扩展)

题意:

给出两个串,求这两个串结合的结果,规则是把重复的部分删去,这两个串都可以做头和尾,那么结果首先选择结合后串最短的,第二选择字典序最小的。

题解:
扩展kmp求最长公共前前缀,对于任意i,如果extend[i]+i==len说明这个是最长的后缀可以输出!!。只要O(n)枚举i即可

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<map>
using namespace std;
//typedef long long lld;
const int oo=0x3f3f3f3f;
//const lld OO=1LL<<61;
const int MOD=10007;
const int maxn=100000+10;
char s1[maxn],s2[maxn],str1[maxn<<1],str2[maxn<<1];
int next[maxn],extend[maxn];

void get_extend(char T[],int len)
{
    int k=0;
    next[k]=len;
    while(k<len-1&&T[k]==T[k+1])k++;
    next[1]=k;
    k=1;
    for(int i=2;i<len;i++)
    {
        int p=k+next[k]-1,L=next[i-k];
        if(i+L-1>=p)
        {
            int j=max(p-i+1,0);
            while(i+j<len&&T[i+j]==T[j])j++;
            next[i]=j;
            k=i;
        }
        else next[i]=L;
    }
}

void Ekmp(char S[],char T[],int lenS,int lenT)
{
    get_extend(T,lenT);
    int k=0;
    while(k<lenT&&k<lenS&&S[k]==T[k])k++;
    extend[0]=k;
    k=0;
    for(int i=1;i<lenS;i++)
    {
        int p=k+extend[k]-1,L=next[i-k];
        if(i+L-1>=p)
        {
            int j=max(p-i+1,0);
            while(i+j<lenS&&j<lenT&&S[i+j]==T[j])j++;
            extend[i]=j;
            k=i;
        }
        else extend[i]=L;
    }
}

int main()
{
    int len1,len2,pos;
    while(scanf("%s%s",s1,s2)!=EOF)
    {
        len1=strlen(s1);
        len2=strlen(s2);
        Ekmp(s1,s2,len1,len2);
        int pos=len1;
        for(int i=0;i<len1;i++)
        {
            if(extend[i]+i==len1)
            {
                pos=i;
                break;
            }
        }
        for(int i=0;i<pos;i++)
            str1[i]=s1[i];
        strcpy(str1+pos,s2);

        Ekmp(s2,s1,len2,len1);
        pos=len2;
        for(int i=0;i<len2;i++)
        {
            if(extend[i]+i==len2)
            {
                pos=i;
                break;
            }
        }
        for(int i=0;i<pos;i++)
            str2[i]=s2[i];
        strcpy(str2+pos,s1);

        len1=strlen(str1);
        len2=strlen(str2);
        if(len1<len2)
            puts(str1);
        else if(len1>len2)
            puts(str2);
        else
        {
            if(strcmp(str1,str2)<0)
                puts(str1);
            else
                puts(str2);
        }
    }
    return 0;
}
/**
asdf sdfg
asdf ghjk
*/








你可能感兴趣的:(hdu 1867 A + B for you again (kmp扩展))