1. 程式人生 > >洛谷P3435 [POI2006]OKR-Period of Words [KMP]

洛谷P3435 [POI2006]OKR-Period of Words [KMP]

ros targe zoj 傳送門 bsp pro prope long http

  洛谷傳送門,BZOJ傳送門

OKR-Period of Words

Description

一個串是有限個小寫字符的序列,特別的,一個空序列也可以是一個串. 一個串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的最大周期是空串. 給出一個串,求出它所有前綴的最大周期長度之和.

Input

第一行一個整數 k ( 1 k 1 000 000) 表示串的長度. 接下來一行表示給出的串.

Output

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

Sample Input

8
babababa

Sample Output

24


  分析:

  又是一道需要深入理解$next[]$數組的題。

  因為$next[i]$表示的是第$i-1$個前綴的最長公共前後綴,那麽不難想到,在$j<=i$且$next[j]$不為$0$的情況下可以得到一個最短後綴,用原串長度減去即可得到答案。

  Code:

  

//It is made by HolseLee on 11th Aug 2018
//Luogu.org P3435 #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<iomanip> #include<algorithm> using namespace std; const int N=2e6+7; int n,nxt[N],k,cnt; long long ans; char s[N]; int main() { scanf(
"%d%s",&n,s); nxt[0]=nxt[1]=0;k=0; for(int i=1;i<n;++i){ while(k&&s[i]!=s[k]) k=nxt[k]; nxt[i+1]=(s[i]==s[k]?++k:0); } int ka; for(int i=1;i<=n;++i){ ka=i; while(nxt[ka])ka=nxt[ka]; if(nxt[i])nxt[i]=ka; ans+=(i-ka); } printf("%lld ",ans); return 0; }

洛谷P3435 [POI2006]OKR-Period of Words [KMP]