HDU 1841 Find the Shortest Common Superstring KMP

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1841


题目有问题题、目有问题——代码1和代码3为什么不能过


题意:给你两个字符串,求解一个最短的字符串,两个字符串连接的时候相同的可以重叠

例如: “alba” 和“bacau”重叠在一起的最短串是 “albacau”。


我感觉这道题用KMP,求next数组就行,先将两个字符串连接起来(两种方法),然后求解next[len],当这个值大于len1或len2时,

继续求解next,最后用len-两个中最大的值,但是这样WA了,个人感觉没错,求解释。

WA代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
using namespace std;

typedef __int64 LL;
const int N=1000005;
const LL II=1000000007;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);

char word[2*N],s1[N],s2[N];
int len,next[2*N];

void getnext(char *p,int wlen)
{
    int j=0,k=-1;
    next[0]=-1;
    while(j<wlen)
    {
        if(k==-1||p[j]==p[k])
        {
            j++;    k++;
            next[j]=k;
        }
        else
            k=next[k];
    }
}

int main()
{
    int ca=0,i,j,T;
    scanf("%d",&T);
    while(T--)
    {
        int len1,len2,t1,t2;
        scanf("%s%s",s1,s2);
        len1=strlen(s1);
        len2=strlen(s2);
        len=len1+len2;

        strcpy(word,s1);
        strcat(word,s2);
        word[len]='\0';
        getnext(word,len);
        t1=next[len];
        while(t1>len1)
            t1=next[t1];

        strcpy(word,s2);
        strcat(word,s1);
        word[len]='\0';
        getnext(word,len);
        t2=next[len];
        while(t2>len2)
            t2=next[t2];

        t1=max(t1,t2);
        printf("%d\n",len-t1);
    }
    return 0;
}




看了别人的博客,发现在这个之前加上一个判断包含关系就过了,

我感觉我上面这个代码也可以判断包含关系啊。

求解释,吾当以身相许

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
using namespace std;

typedef __int64 LL;
const int N=1000005;
const LL II=1000000007;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);

char word[2*N],s1[N],s2[N];
int len,next[2*N];

void getnext(char *p,int wlen)
{
    int j=0,k=-1;
    next[0]=-1;
    while(j<wlen)
    {
        if(k==-1||p[j]==p[k])
        {
            j++;    k++;
            next[j]=k;
        }
        else
            k=next[k];
    }
}

int kmp(char *text,char *word)
{
    int i=0,j=0,k=0,wlen=strlen(word),tlen=strlen(text);
    while(i<tlen)//i指向text,j指向word
    {
        if(j==-1||text[i]==word[j])
        {       i++;j++;        }
        else
            j=next[j];      // 当j=0时,next[j]=-1
        if(j==wlen)
            return tlen;
    }
    return 0;//检查text串中含有word串的个数
}

int main()
{
    int ca=0,i,j,T;
    scanf("%d",&T);
    while(T--)
    {
        int len1,len2,t1,t2;
        scanf("%s%s",s1,s2);
        len1=strlen(s1);
        len2=strlen(s2);
        len=len1+len2;

        if(len1>len2)
        {
            swap(len1,len2);
            strcpy(word,s1);
            strcpy(s1,s2);
            strcpy(s2,word);
        }
        getnext(s1,len1);
        int Min=kmp(s2,s1);
        if(Min>0)
        {
            printf("%d\n",Min);
            continue;
        }

        strcpy(word,s1);
        strcat(word,s2);
        word[len]='\0';
        getnext(word,len);
        t1=next[len];
        while(t1>len1||t1>len2)
            t1=next[t1];

        strcpy(word,s2);
        strcat(word,s1);
        word[len]='\0';
        getnext(word,len);
        t2=next[len];
        while(t2>len1||t2>len2)
            t2=next[t2];

        t1=max(t1,t2);
        printf("%d\n",len-t1);
    }
    return 0;
}


又看了HDU1867,一模一样的,然后果断又改了一遍,提交,果断又WA了,

真心不知道哪里错了,哎………………悲催………………

WA代码:(感觉是对的)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
using namespace std;

typedef __int64 LL;
const int N=1000005;
const LL II=1000000007;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);

char s1[N],s2[N];
int len,next[N];

void getnext(char *p,int wlen)
{
    int j=0,k=-1;
    next[0]=-1;
    while(j<wlen)
    {
        if(k==-1||p[j]==p[k])
        {
            j++;    k++;
            next[j]=k;
        }
        else
            k=next[k];
    }
}

int kmp(char *text,char *word)
{
    int i=0,j=0,tlen=strlen(text);
    while(i<tlen)
    {
        if(j==-1||text[i]==word[j])
            j++,i++;
        else
            j=next[j];
    }
    return j;
}

int main()
{
    int ca=0,i,j,T;
    cin>>T;
    while(T--)
    {
        scanf("%s%s",s1,s2);
        int len1,len2,t1,t2;
        len1=strlen(s1);
        len2=strlen(s2);

        getnext(s2,len2);
        t1=kmp(s1,s2);//s2模式串
        getnext(s1,len1);
        t2=kmp(s2,s1);//s1模式串
        int len=len1+len2;
        printf("%d %d\n",t1,t2);
        if(t1==t2)
            printf("%d\n",len-t1);
        else
            printf("%d\n",t1>t2?len-t1:len-t2);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值