HDU 1841 Find the Shortest Common Superstring(KMP灵活运用)

ind the Shortest Common Superstring

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 1149    Accepted Submission(s): 289


Problem Description
The shortest common superstring of 2 strings S 1 and S 2 is a string S with the minimum number of characters which contains both S 1 and S 2 as a sequence of consecutive characters. For instance, the shortest common superstring of “alba” and “bacau” is “albacau”.
Given two strings composed of lowercase English characters, find the length of their shortest common superstring. 
 

Input
The first line of input contains an integer number T, representing the number of test cases to follow. Each test case consists of 2 lines. The first of these lines contains the string S 1 and the second line contains the string S 2. Both of these strings contain at least 1 and at most 1.000.000 characters.
 

Output
For each of the T test cases, in the order given in the input, print one line containing the length of the shortest common superstring.
 

Sample Input
   
   
   
   
2 alba bacau resita mures
 

Sample Output
   
   
   
   
7 8
 

                  
           题目大意:给你两个串,求出一个最小长度的串能把这两个串都包含进去。输出其长度
 
           解题思路:自己开始直接把两个串分别首尾连接起来变成两个长串,然后再求其最小循环节。最后WA了,看了DISCUSS里面,发现自己abcde bcd这个数据不能过,主要就是本身一个串把另一个串包含进去了,那样的话就不是首尾相连的局面了。所以需要首先预处理判断一下两个串是不是直接包含关系,是的话,就直接输出了。自己开始没想到这个方法,直接用了解决3450那样的方法,暴力对长度小的串枚举,然后匹配。不过那样超时了。因为长度有10^5还是比较大的,再O(n^2)时间直接超出了10^9.

           题目地址:Find the Shortest Common Superstring

AC代码:
/*
   不能直接求next数组,可能有这样的数据,并不一定是首尾相连的
   abcde bcd   答案是5
   abcde qbc   答案是8
   abcde ebcd  答案输出8
   先判断直接包含与否,如果不包含,再连接求next就够了
*/

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
char s1[1000005],s2[1000005],s3[2000005],s4[2000005],s[1000005];
int len1,len2,len,next[2000005];

void getnext(char *p,int len)    //p是模式串
{
     int i,j;
     next[0]=0,next[1]=0;
     for(i=1;i<len;i++)
     {
          j=next[i];
          while(j&&p[i]!=p[j])
               j=next[j];
          if(p[i]==p[j])
               next[i+1]=j+1;
            else
               next[i+1]=0;
     }
}

int KMP(char *p,int lenp,char *a,int lena)
{
     int i,j=0;
     for(i=0;i<lena;i++)
     {
          while(j&&a[i]!=p[j])
               j=next[j];
          if(a[i]==p[j])
               j++;
          if(j==lenp)
             return 1;
     }
     return 0;
}

int main()
{
     int T;
     scanf("%d",&T);
     getchar();
     while(T--)
     {
         gets(s1);
         gets(s2);
         len1=strlen(s1),len2=strlen(s2);
         if(len1>len2)
         {
              strcpy(s,s1);
              strcpy(s1,s2);
              strcpy(s2,s);
         }
         len1=strlen(s1),len2=strlen(s2);
         getnext(s1,len1);
         if(KMP(s1,len1,s2,len2))  //s2包含了s1
            printf("%d\n",len2);
         else
         {
              strcpy(s3,s1); strcat(s3,s2);  //s3=s1+s2;
              strcpy(s4,s2); strcat(s4,s1);  //s4=s2+s1;
              len=len1+len2;
              int res;
              getnext(s3,len);
              res=len-next[len];  //最小循环节,可以接上
              getnext(s4,len);
              if(res>(len-next[len]))
                res=len-next[len];
              if(res<len2)   //不能小于两个的长度
                res=len2;
              printf("%d\n",res);
         }
     }

     return 0;
}




你可能感兴趣的:(KMP,HDU,最小循环节)