hdu - 1867 - A + B for you again


A + B for you again

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7687    Accepted Submission(s): 1921


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
 

题意概括:

先确定s1和s2相同的部分并输出s1中相同部分之前的串、相同部分和s2中相同部分之后的串。

解题分析:

水题。进行两次KMP,然后读懂题意就可以了。主要就是判断s1的后缀和s2的前缀相等,然后输出s1相同部分之前的字

符、相同部分和s2相同部分之后的字符。因为在对s1和s2进行KMP时,它俩都可以作为文本串和模板串,所以要进行两

次KMP。当两次KMP返回的值不相等时,就要用值大的那个(KMP返回的值是两个字符串前后缀相等的长度)。如果两

个返回值相等再按字母表顺序输出(这里就包含了两个串不相等的情况了)。

需要注意的是“asdfwedf”, “df” 这组数据如果用一般的KMP是卡不住这组数据的(虽然OJ中没有这组数据大笑)。

通常KMP中循环的结束是当两个字符串有一个结束就结束循环,然后判断一下文本串是否跑完处理一下返回值就可以了。如下:

int KMP(char s[], char t[])
{
    get_next(t);
    int i = 0, j = 0, l1, l2;
    l1 = strlen(s);
    l2 = strlen(t);
    while(i < l1 && j < l2){//结束条件
        if(j == 0 && s[i] != t[j])
            i++;
        else if(j > 0 && s[i] != t[j])
            j = Next[j-1];
        else{
            i++;
            j++;
        }
    }
    if(i == l1)//处理返回值
        return j;
    return 0;
}
但是这是卡不住刚才说的数据的,因为它的两次KMP的值都会是0,输出是“asdfwedfdf”,但它的正确输出应该是“asdfwedf”才对。

其中的原因只要理解了KMP的处理过程就不难想出来了。

话不多说了直接上代码吧,聪明的你一看就懂。

AC代码:

#include<stdio.h>
#include<string.h>


#define N 100010


int Next[N];
char s1[N], s2[N];


void get_next(char str[])
{
    int i = 1, j = 0, len;
    len = strlen(str);
    while(i < len){
        if(j == 0 && str[i] != str[j]){
            Next[i] = 0;
            i++;
        }
        else if(j > 0 && str[i] != str[j])
            j = Next[j-1];
        else{
            Next[i] = j+1;
            i++;
            j++;
        }
    }
}
int KMP(char s[], char t[])
{
    get_next(t);
    int i = 0, j = 0, l1, l2;
    l1 = strlen(s);
    l2 = strlen(t);
    while(i < l1){//这里必须要把s串跑完,不然会造成bug,漏掉情况。虽然按一般的形式写也能AC
        if(j == 0 && s[i] != t[j])
            i++;
        else if(j > 0 && s[i] != t[j])
            j = Next[j-1];
        else{
            i++;
            j++;
        }
    }
    return j;
}


int main()
{
    int k, k1, k2;
    while(~scanf("%s%s", s1, s2)){
        k1 = KMP(s1, s2);
        k2 = KMP(s2, s1);
        if(k1 == k2){
            if(strcmp(s1, s2) == -1)
                printf("%s%s\n", s1, s2+k1);
            else
                printf("%s%s\n", s2, s1+k1);
        }
        else if(k1 > k2)
            printf("%s%s\n", s1, s2+k1);
        else
            printf("%s%s\n", s2, s1+k2);
    }
    return 0;
}



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值