HDU 1867 A + B for you again(简单KMP)

A + B for you again

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


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
 

                   
           题目大意:将两个串连接起来,首尾相同的可以消去。找最短的串,如果存在多组(最多就两组),输出字典序小的.

           解题思路:看到题目会立马想到连接串,求最小循环节,这个题比较麻烦的点就在于需要把这个串输出来。所以就需要保存这个串,中间出了点小问题,所以调了大几十分钟,详解见代码。

AC代码:
/*
   aa aa   答案是 aa
   asdf sd 答案是 asdfsd
   asdf df 答案是 asdf
*/

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
char s1[1000005],s2[1000005],s3[2000005],s4[2000005];
char ans[2000005],ans1[2000005],ans2[2000005];
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 main()
{
     int i;
     while(~scanf("%s%s",s1,s2))
     {
          len1=strlen(s1),len2=strlen(s2);
          int ma=len1>len2?len1:len2;

          strcpy(s3,s1); strcat(s3,s2);  //s3=s1+s2;
          strcpy(s4,s2); strcat(s4,s1);  //s4=s2+s1;
          len=len1+len2;
          int res1,res2;
          getnext(s3,len);
          res1=len-next[len];  //最小循环节,可以接上
          getnext(s4,len);
          res2=len-next[len];

          if(res1<res2&&res1>ma)
          {
               int q=len-res1;
               strcpy(ans,s2);
               for(i=len2;i<res1;i++)
                    ans[i]=s1[q++];
               ans[res1]='\0';
          }
            else if(res2<res1&&res2>ma)
            {
                int q=len-res2;
                strcpy(ans,s1);
                for(i=len1;i<res2;i++)
                    ans[i]=s2[q++];
                ans[res2]='\0';
            }
             else if(res1==res2&&res1>ma)   //需要比较两个的字典序
             {
                  int q=len-res1;
                  strcpy(ans1,s2);
                  for(i=len2;i<res1;i++)
                    ans1[i]=s1[q++];
                  ans1[res1]='\0';
                  q=len-res2;
                  strcpy(ans2,s1);
                  for(i=len1;i<res2;i++)
                     ans2[i]=s2[q++];
                  ans2[res2]='\0';
                  if(strcmp(ans1,ans2)>0)
                     strcpy(ans,ans2);
                   else
                      strcpy(ans,ans1);
             }
              else    //这个时候,出现了包含的情况
              {
                   if(len1<len2)
                     strcpy(ans,s2);
                   else if(len2<len1)
                     strcpy(ans,s1);
                   else
                   {
                      if(strcmp(s1,s2)>0)   //两个直接连接也需要判断字典序
                        strcpy(ans,s2);
                       else
                         strcpy(ans,s1);
                   }
              }

           printf("%s\n",ans);

     }

     return 0;
}




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