KMP-Acwing-週期

KMP-Acwing-週期

題目:

一個字符串的前綴是從第一個字符開始的連續若干個字符,例如”abaab”共有5個前綴,分別是a, ab, aba, abaa, abaab。

我們希望知道一個N位字符串S的前綴是否具有循環節。

換言之,對於每一個從頭開始的長度爲 i (i>1)的前綴,是否由重複出現的子串A組成,即 AAA…A (A重複出現K次,K>1)。

如果存在,請找出最短的循環節對應的K值(也就是這個前綴串的所有可能重複節中,最大的K值)。

輸入格式
輸入包括多組測試數據,每組測試數據包括兩行。

第一行輸入字符串S的長度N。

第二行輸入字符串S。

輸入數據以只包括一個0的行作爲結尾。

輸出格式
對於每組測試數據,第一行輸出 “Test case #” 和測試數據的編號。

接下來的每一行,輸出具有循環節的前綴的長度i和其對應K,中間用一個空格隔開。

前綴長度需要升序排列。

在每組測試數據的最後輸出一個空行。

數據範圍
2≤N≤1000000
輸入樣例:
3
aaa
4
abcd
12
aabaabaabaab
0
輸出樣例:
Test case #1
2 2
3 3

Test case #2

Test case #3
2 2
6 2
9 3
12 4

題意:

nnin[i]1<=i<=n2求給定長度爲n的字符串的n個前綴中,長度爲i的“循環節”,以及“循環節”的個數n[i],1<=i<=\frac{n}{2}。

aabaabaabaab2"aa"a26"aabaab"aab29"aabaabaab"aab312"aabaabaabaab"aab4樣例:aabaabaabaab\\長度爲2的前綴"aa"的循環節爲a,有2個。\\長度爲6的前綴"aabaab"的循環節爲aab,有2個。\\長度爲9的前綴"aabaabaab"的循環節爲aab,有3個。\\長度爲12的前綴"aabaabaabaab"的循環節爲aab,有4個。

題解:

首要問題是如何找出循環節。

KMP通過KMP算法:
在這裏插入圖片描述
KMPNext[j]j1Next[j]=lKMP算法中:數組Next[j]的含義指前j-1個字符構成的子串的最長相同前後綴的長度,設Next[j]=l。

l那麼可知紅色部分前綴與藍色部分後綴長度相等,都爲l。從而可知綠色圈圈部分的兩條線段長度相等。

下面一根線段是紅色部分前綴,將其平移,每一段均與藍色後綴部分對應相等,

2=53=64=71=51=22=62=33=73=41=2=3=41234即2=5,3=6,4=7,由1=5知1=2,由2=6知2=3,由3=7知3=4,所以1=2=3=4,\\1,2,3,4即該字符串的循環節。

j1jNext[j]Next[j]於是前j-1個子串的循環節的最小長度就是j-Next[j],這必然是最小的循環節,\\這是因爲Next[j]數組存儲的是相同前後綴的最大長度。

i/t循環節的個數即: 子串長度i/循環節長度t。

ti注意:判定是否爲循環節還需判斷t能否整除i,若不能,則說明不能形成循環節。


代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int N=1e6+10;
int Next[N];
char str[N];
int n;

void get_table()
{
    for(int i=2,j=0;i<=n;i++)
    {
        while(j&&str[i]!=str[j+1]) j=Next[j];
        if(str[i]==str[j+1]) j++;
        Next[i]=j;
    }
}
int main()
{
    int T=1;
    while(~scanf("%d",&n),n)
    {
        scanf("%s",str+1);
        
        get_table();

        printf("Test case #%d\n",T++);
        for(int i=2;i<=n;i++)
        {
            int t = i - Next[i];
            if (i > t && i % t == 0) printf("%d %d\n", i, i / t);   ///判斷條件
        }
        puts("");
    }

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章