1. 程式人生 > >HDU 2203 親和串 kmp演算法

HDU 2203 親和串 kmp演算法

題意:

Problem Description 人隨著歲數的增長是越大越聰明還是越大越笨,這是一個值得全世界科學家思考的問題,同樣的問題Eddy也一直在思考,因為他在很小的時候就知道親和串如何判斷了,但是發現,現在長大了卻不知道怎麼去判斷親和串了,於是他只好又再一次來請教聰明且樂於助人的你來解決這個問題。
親和串的定義是這樣的:給定兩個字串s1和s2,如果能通過s1迴圈移位,使s2包含在s1中,那麼我們就說s2 是s1的親和串。

Input 本題有多組測試資料,每組資料的第一行包含輸入字串s1,第二行包含輸入字串s2,s1與s2的長度均小於100000。

Output 如果s2是s1的親和串,則輸出"yes",反之,輸出"no"。每組測試的輸出佔一行。

思路:首先把目標串複製一份拼接到自己後面,然後直接kmp去匹配

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 100010;
char s1[N*2], s2[N];
int nt[N];
void getnt()
{
    int i = 0, j = - 1;
    nt[0] = -1;
    while(s2[i])
    {
        if(j == -1 || s2[i] == s2[j])
        {
            i++, j++;
            if(s2[i] != s2[j]) nt[i] = j;
            else nt[i] = nt[j];
        }
        else j = nt[j];
    }
}
bool kmp()
{
    getnt();
    int i = 0, j = 0;
    while(s1[i])
    {
        if(j == -1 || s1[i] == s2[j])
            i++, j++;
        else j = nt[j];
        if(j != -1 && !s2[j])
            return true;
    }
    return false;
}

int main()
{
    while(~ scanf("%s", s1))
    {
        scanf("%s", s2);
        int len = strlen(s1);
        for(int i = len; i < len * 2; i++)
            s1[i] = s1[i-len];
        s1[len*2] = '\0';
        if(kmp()) printf("yes\n");
        else printf("no\n");
    }
    return 0;
}