bzoj3790 神奇項鍊

傳送門
記一下貪心的方法:從左往右掃。每個迴文左端點記錄了迴文右端點的位置。
lastlast記錄上次的最右端。maxRmaxR記錄從ii往右走到lastlast過程中的最右端。
初始化last=maxR=T[0]last=maxR=T[0]maxRmaxR會在移動的過程中不斷更新。
ii越過lastlast時,表示已經跨過覆蓋的最大範圍了。ans+=1,記錄跨過的這個迴文串。
然而最後一個串的右端點一定在整個串的右端點。跨過了之後退出循環。ans記錄不到。
所以整個串覆蓋至少需要(ans+1)個迴文串。需要連接ans次。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
char s[maxn];int R[maxn],N,T[maxn],now,to,ans=0,last,maxR;
inline void manacher(){
	int p=0,mx=0;
	for(int i=0;i<=N;++i){
		R[i]=(mx>i)?(min(mx-i+1,R[p*2-i])):1;
		while(i>=R[i]&&s[i+R[i]]==s[i-R[i]]) R[i]++;
		if(i+R[i]-1>mx) mx=i+R[i]-1,p=i;
		T[i-R[i]+1]=max(T[i-R[i]+1],i+R[i]-1);
	}
}
int main(){
	while(scanf("%s",s)!=EOF){
		memset(T,0,sizeof(T)),N=strlen(s),now=0,ans=0;
		for(int i=N-1;i>=0;i--) s[(i+1)<<1]='#',s[(i<<1)+1]=s[i];
		s[0]='#',N<<=1,manacher();
		last=maxR=T[0];
		for(int i=0;i<=N;i+=2){
			if(i>last) ans++,last=maxR;
			maxR=max(maxR,T[i]);
		}printf("%d\n",ans);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章