原题:http://acm.hdu.edu.cn/showproblem.php?pid=1867
题意:
给你两个字符串T和P,将他们相连(T在P前面,P在T前面均可),首先要求尽可能多的覆盖住重复部分,其次满足按字典序输出;
思路:
用KMP分别求出两种情况下的匹配数,选取匹配数多的那一种;
当两者的匹配数相等时,选取字典序小的字符串在前面;
#include<stdio.h>
#include<string.h>
const int maxn = 1e5+5;
char T[maxn], P[maxn];
int f[maxn];
void getFail(char *P)
{
int m = strlen(P);
f[0] = f[1] = 0;
for(int i = 1; i < m; i++)
{
int j = f[i];
while(j && P[i] != P[j] ) j = f[j];
if(P[i] == P[j])
f[i+1] = j+1;
else
f[i+1] = 0;
}
}
int find(char *T, char *P)
{
int n = strlen(T);
int m = strlen(P);
getFail(P);
int j = 0;
for(int i = 0; i < n; i++)
{
while(j && T[i] != P[j]) j = f[j];
if(T[i] == P[j]) j++;
if(i == n-1)
return j;
}
}
int main()
{
while(scanf("%s%s", T, P)!=EOF)
{
int len1 = find(T, P);
int len2 = find(P, T);
if(len1>len2)
{
printf("%s", T);
printf("%s\n", P+len1);
}
if(len2>len1)
{
printf("%s", P);
printf("%s\n", T+len2);
}
if(len1 == len2)
{
if(strcmp(T, P)<0)
{
printf("%s", T);
printf("%s\n", P+len1);
}
else
{
printf("%s", P);
printf("%s\n", T+len2);
}
}
}
return 0;
}