A + B for you again
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
题目要求:
1、求和字符串最短;2、字典序最小;
由题意,串一的最长的后缀匹配串二的最长前缀或整个串二,这两个串可以交换位置; 比如 abc abc = abc 、 aaaa aa =aaaa 、abcd cd = abcd 、abcd cb= abcdcb。
思路:
KMP模板,然后先把b串当模式串与a串比较得到 j 的的位置x,再把a串当模式串与b串比较得到 j 的位置y,如果x = y,说明到j的位置相等,然后比较a,b的长度,谁短先输出谁;如果x > y,先输出a串,再输出相应 j 位置后的b串;如果x < y,先输出 b 串,在输出相应位置 j 后的a串。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn=100000+10;
int nax[maxn];
char s1[maxn],s2[maxn];
void maknext(int n,char *a)//求next数组
{
int i,j;
nex[0]=0;
for(i=1,j=0; i<n ; i++)
{
while(j>0&&a[i]!=a[j])
j=nex[j-1];
if(a[i]==a[j])
j++;
nex[i]=j;
}
}
int KMP(int n,int m,char *a,char *b)
{
maknext(m,b);
int i,j;
for(i=0,j=0; i<n; i++)
{
while(j>0&&a[i]!=b[j])
j=nex[j-1];
if(a[i]==b[j])
j++;
if(j==m)
break;
}
if((i==n-1&&j==m)||i==n) //只能是模式串匹配到主串结束
return j;
return 0;
}
int main()
{
while(scanf("%s%s",s1,s2)!=EOF)
{
int len1=strlen(s1);
int len2=strlen(s2);
int b=KMP(len1,len2,s1,s2);//s2当模式串
int a=KMP(len2,len1,s2,s1);//s1当模式串
if(b>a) //s2的前缀与s1的后缀匹配较长
{
printf("%s%s\n",s1,s2+b);
}
else if(a>b)//s1的前缀与s2的后缀匹配较长
{
printf("%s%s\n",s2,s1+a);
}
else //如果匹配长度相等则看字典序从小到大
{
if(strcmp(s1,s2)<0) printf("%s%s\n",s1,s2+b);
else printf("%s%s\n",s2,s1+a);
}
}
return 0;
}