题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1867
题目描述:给定两个串s1,s2,让s1与s2合并,如果某个串的前缀和另一个串的后缀相等,则应去掉前缀,比如s1 = "abc"与 s2 = "bcd",则合并后为"abcd".要求答案竟可能短且字典序尽可能小。
解题思路:与 hdu 2594 Simpsons’ Hidden Talents这题相似,也可以说是升级版。本题要找两次next数组,一次是s1+s2,一次是s2+s1,最后把公共部分去掉。这题wa了3次,前两次是s1与s2写混了,第三次是在求最优解时的判断语句写错了,'=='写成了'<',改后就A了。字符串的题目就是要注意细节。
测试数据:
kj sd
abcd bcda
xxoo xo
baabbab ab
ccc bbb
cbac cba
asdf sdfg
sdfg asdf
asdf ghjk
aaaa aaa
fuck uck
代码:
#include <stdio.h>
#include <string.h>
#define MAX 100010
int next[MAX*2],maxx,l1,l2;
char s1[MAX],s2[MAX],s3[MAX*2];
char temp[MAX*2],ans[MAX*2];
void getnext(char *s,char *s1,char *s2) {
int i,j,k;
int len1,len2;
len1 = strlen(s1);
len2 = strlen(s2);
i = 0,j = -1;
next[0] = -1;
while (s[i]) {
if (j == -1 || s[i] == s[j])
i++,j++,next[i] = j;
else j = next[j];
}
if (next[i] > -1) {
maxx = next[i];
for (j = 0; j < len2; ++j)
temp[j] = s2[j];
for (k = maxx; k < len1; ++k)
temp[j++] = s1[k];
temp[j] = '\0';
if (ans[0] == '\0' || strlen(temp) < strlen(ans)
|| strlen(temp) == strlen(ans) && strcmp(ans,temp) > 0)
strcpy(ans,temp);
}
}
void Solve() {
strcpy(s3,s1);
strcat(s3,"*");
strcat(s3,s2);
getnext(s3,s1,s2);
strcpy(s3,s2);
strcat(s3,"*");
strcat(s3,s1);
getnext(s3,s2,s1);
}
int main()
{
int i,j,k;
while (scanf("%s%s",s1,s2) != EOF) {
ans[0] = '\0';
l1 = strlen(s1);
l2 = strlen(s2);
Solve();
if (ans[0] == '\0') {
if (strcmp(s1,s2) < 0)
printf("%s%s\n",s1,s2);
else printf("%s%s\n",s2,s1);
}
else printf("%s\n",ans);
}
}