1. 程式人生 > 實用技巧 >P3435 [POI2006]OKR-Periods of Words KMP演算法擴充套件

P3435 [POI2006]OKR-Periods of Words KMP演算法擴充套件

題意:

對於一個僅含小寫字母的字串$q,p$ 為 \(a\) 的字首且 \(a \ne p\),那麼我們稱 \(p\)\(a\) 的 proper 字首。

規定字串 \(Q\)(可以是空串)表示 \(a\) 的週期,當且僅當 \(Q\)\(a\) 的 proper 字首且 \(a\) 是 $Q+Q$的字首。

例如 ababab 的一個週期,因為 ababab 的 proper 字首,且 ababab+ab 的字首。

求給定字串所有字首的最大週期長度之和。

範圍&性質:$1\le k\le 10^6$

分析:

借用別人的圖,侵刪

這裡利用了next陣列的性質:$next[i]$表示$i$的最長的字首和字尾相同的長度

如圖可得對於字串$i$,令$j=i$,然後在$j>0$的情況下令$j=next[j]$最大週期就是$i-j$

程式碼:

#include<bits/stdc++.h>

using namespace std;

namespace zzc
{
	const int maxn = 1e6+5;
	int n;
	long long ans;
	char ch[maxn];
	int nxt[maxn];
	
	void work()
	{
		scanf("%d",&n);
		scanf("%s",ch+1);
		for(int i=2,j=0;i<=n;i++)
		{
			while(j&&ch[i]!=ch[j+1]) j=nxt[j];
			if(ch[i]==ch[j+1]) j++,nxt[i]=j;
		}
		for(int i=2,j=2;i<=n;i++,j=i)
		{
			while(nxt[j]) j=nxt[j];
			if(nxt[i]) nxt[i]=j;
			ans+=i-j;
		}
		printf("%lld",ans);
	}
	
}

int main()
{
	zzc::work();
	return 0;
}