HDU 1867 A + B for you again (KMP两次匹配)

Problem Description


Generally speaking, there are a lot of problems about strings processing. Now you encounter another such problem. If you get two strings, such as “asdf” and “sdfg”, the result of the addition between them is “asdfg”, for “sdf” is the tail substring of “asdf” and the head substring of the “sdfg” . However, the result comes as “asdfghjk”, when you have to add “asdf” and “ghjk” and guarantee the shortest string first, then the minimum lexicographic second, the same rules for other additions.
 

Input


For each case, there are two strings (the chars selected just form ‘a’ to ‘z’) for you, and each length of theirs won’t exceed 10^5 and won’t be empty.
 

Output


Print the ultimate string by the book.
 

Sample Input


asdf sdfg

asdf ghjk
 

Sample Output


asdfg

asdfghjk

给你两个字符串,输出他们合并之后的字符串,合并的时候把A的后缀和B的前缀重叠合(或者把A的前缀和B的后缀重合)。要求合并后的串既包含A右包含B,且使得合并后的字符串尽量短,其次是使得合并后的字符串字典序尽量小.

  首先A和B合并他们一定是首尾重叠相连,要求合并后字典序最小,所以当合并后串长度一样时,我们要把A或B中字典序小的放在前面。

       然后计算A的后缀和B的前缀匹配长度为len1,计算A的前缀和B的后缀匹配长度为len2。

       如果len1大,那么就把A放前面。如果len2大,那么就把B放前面。

AC代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#include<queue>
#include<map>
#include<set>
#include<iomanip>
#include<math.h>
using namespace std;
typedef long long ll;
typedef double ld;

const int MAXN=100000+1000;
char *S,*T;
char str1[MAXN],str2[MAXN];
int next[MAXN];
int n,m;
void getFail(char *T)
{
    next[0]=next[1]=0;
    for(int i=1; i<m; i++)
    {
        int j=next[i];
        while(j && T[i]!=T[j])
            j=next[j];
        next[i+1] = (T[i]==T[j])?j+1:0;
    }
}
int KMP(char *S,char *T)
{
    int j=0;
    n=strlen(S);
    m=strlen(T);
    getFail(T);
    for(int i=0; i<n; i++)
    {
        while(j && S[i]!=T[j])
            j=next[j];
        if(S[i]==T[j])
            j++;
        if(i==n-1)
            return j;
    }
}
int main()
{
    while(scanf("%s%s",str1,str2)==2)
    {
        int len1=KMP(str1,str2);
        int len2=KMP(str2,str1);
        if(len1==len2)
        {
            if(strcmp(str1,str2)<0)
            {
                printf("%s",str1);
                printf("%s\n",str2+len1);
            }
            else
            {
                printf("%s",str2);
                printf("%s\n",str1+len2);
            }
        }
        else if(len1<len2)
        {
            printf("%s",str2);
            printf("%s\n",str1+len2);
        }
        else
        {
            printf("%s",str1);
            printf("%s\n",str2+len1);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值