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

来源:互联网 发布:app开发编程 编辑:程序博客网 时间:2024/05/16 15:27

题意:

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

题解:
扩展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 sdfgasdf ghjk*/




0 0
原创粉丝点击