傳送門
記一下貪心的方法:從左往右掃。每個迴文左端點記錄了迴文右端點的位置。
記錄上次的最右端。記錄從往右走到過程中的最右端。
初始化,會在移動的過程中不斷更新。
當越過時,表示已經跨過覆蓋的最大範圍了。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);
}
}