Hdu 2203 亲和串

思路:第一次写的时候是通过循环移位加KMP算法,结果超时了。第二次写直接将第一个字符串接在第一个字符串的后面。

引用:

该题请求一个串轮回后是否包含别的一个串,其实只要将母串反复一次再进行KMP匹配就行了,因为在反复母串的过程中,其实据已经将轮回后的所有可能都列举出来了,比如串 "ABCD" 反复后为  "ABCDABCD" 在这个串中 "BCDA" , "CDAB" 以及 "DABC" 都接踵呈现了。用该种办法求解的过程中还应重视当子串长度跨越母串时不进行匹配,因为那样可能输失足误的断定,比如上例中子串为 "ABCDA" 那么也会输出 yes 了。

 

CODE

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

const  int SIZE =  100001;

char sz1[SIZE* 2+ 10];
char sz2[SIZE];
int nextval[SIZE];
int N, M;


void KMP( int len1,  int len2)
{
     int i, j;
    i =  0;     j =  0;
     while(i < len1 && j < len2)
    {
         if(j == - 1 || sz1[i] == sz2[j])
        {
            i++;
            j++;
        }
         else
        {
            j = nextval[j];
        }
    }
     if(j >= M) printf( " yes\n ");
     else printf( " no\n ");
}



void get_nextval( int len2)
{
     int i, j;
    i =  0;     nextval[ 0] = - 1;     j = - 1;
     while(i < M)
    {
         if(j == - 1 || sz2[i] == sz2[j])
        {
            ++i;    ++j;
             if(sz2[i] != sz2[j])    nextval[i] = j;
             else    nextval[i] = nextval[j];
        }
         else j = nextval[j];
    }
}



int main()
{
     int i, j;
     while(~scanf( " %s%s ", sz1, sz2))
    {
       memset(nextval,  0sizeof(nextval));
       N = strlen(sz1);    M = strlen(sz2);
        if(N < M)
       {
         printf( " no\n ");
          continue;
       }
        for(i =  0; i < N; i++)
       {
          sz1[i+N] = sz1[i];
       }
       sz1[ 2*N- 1] =  ' \0 ';
       get_nextval(M);
       KMP( 2*N- 1, M);
    }
     return  0;
}

你可能感兴趣的:(HDU)