OKR-Periods of Words【KMP最小前後綴】

OKR-Periods of Words

傳送門:鏈接    來源:UPC 8180

題目描述

串是有限個小寫字符的序列,特別的,一個空序列也可以是一個串。一個串P是串A的前綴,當且僅當存在串B,使得A=PB。如果P≠A並且P不是一個空串,那麼我們說P是A的一個proper前綴。
定義Q是A的週期,當且僅當Q是A的一個proper前綴並且A是QQ的前綴(不一定要是proper前綴)。比如串abab和ababab都是串abababa的週期。串A的最大週期就是它最長的一個週期或者是一個空串(當A沒有周期的時候),比如說,ababab的最大週期是abab。串abc的最大週期是空串。
給出一個串,求出它所有前綴的最大週期長度之和。

輸入

第一行一個整數k,表示串的長度。
接下來一行表示給出的串。

輸出

輸出一個整數表示它所有前綴的最大週期長度之和。

 

樣例輸入

8
babababa

樣例輸出

24

提示

對於全部數據,1<k<106

思路:

kmp算法中的Next[i]代表的是最大前後綴,即位置i的前後綴最大的相同長度爲Next[i](若Next[0]=-1,長度即爲Next[i]+1)。

這個題要求的是最小相同的前後綴(滿足題目中週期的定義),可能不太好理解,看下圖:(Next[0]=-1)

對應Next值:

求法:先正常求出Next數組,對每個Next[i]回溯到第一個不爲-1的位置,並賦值給Next[i]

例如當i=5時,Next[5]=Next[Next[5]]=1,其餘同理。

AC代碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MAX=1e6;
LL Next[MAX+5];
void getNext(string p,LL lp,LL Next[])
{
    LL k=-1;
    Next[0]=-1;
    for(LL i=1;i<lp;i++){
        while(k>-1&&p[k+1]!=p[i]) k=Next[k];
        if(p[k+1]==p[i]) k++;
        Next[i]=k;
    }
}
 
int main()
{
    LL lp;
    string p;
    cin>>lp>>p;
    getNext(p,lp,Next);
    for(LL i=0;i<lp;i++){
        if(Next[i]==-1) continue;
        else{
            while(Next[Next[i]]!=-1){
                Next[i]=Next[Next[i]];
            }
        }
    }
    LL sum=0;
    for(LL i=0;i<lp;i++){
        if(Next[i]!=-1)
            sum+=(i-Next[i]);
    }
    cout<<sum<<endl;
    return 0;
}

 

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