题目大意:给你一个串,求这个串被最少数量的回文串拼起来的次数,两个回文串可以重叠拼接,但必须保证重叠的部分完全相同
先用$Manacher$预处理出最长回文半径$p_{i}$。
再用最长双回文串的方法,处理出数组$e_{i}$,以$i$为开头最长回文串结尾的位置
在已经被遍历到的位置中,选择$e_{i}$最大的位置$maxx$,说明再拼接一次,最远能到达的位置是$maxx$,$ans++$
然后在$i~maxx$取最大的,重复上述过程,继续取$maxx$,直到串的末尾,$ans++$
这其实是个贪心,在能往下拼接的位置中,选取最远能拼到的位置,然后继续拼......
1 #include <cmath> 2 #include <queue> 3 #include <vector> 4 #include <cstdio> 5 #include <cstring> 6 #include <algorithm> 7 #define NN 200100 8 #define MM 1510 9 #define ll long long 10 #define dd double 11 #define uint unsigned int 12 #define mod 1000000007 13 #define idx(X) (X-'a') 14 #define eps (1e-9) 15 using namespace std; 16 17 int n,nn; 18 char str[NN],a[NN]; 19 int p[NN],e[NN]; 20 void init() 21 { 22 memset(a,0,sizeof(a)); 23 memset(e,0,sizeof(e)); 24 memset(p,0,sizeof(p)); 25 } 26 27 int main() 28 { 29 //freopen("t1.in","r",stdin); 30 while(scanf("%s",str+1)!=EOF) 31 { 32 n=strlen(str+1); 33 init(); 34 a[1]='#';nn=n*2+1; 35 for(int i=1;i<=n;i++) 36 a[2*i]=str[i],a[2*i+1]='#'; 37 p[1]=1;int mid=1,mr=0; 38 for(int i=2;i<=nn;i++){ 39 if(i<mr) 40 p[i]=min(p[2*mid-i],mr-i); 41 else 42 p[i]=1; 43 for(;a[i+p[i]]==a[i-p[i]]&&p[i]+1<=i;p[i]++); 44 if(i+p[i]>mr) 45 mr=i+p[i],mid=i; 46 e[i-p[i]+1]=max(e[i-p[i]+1],i+p[i]-1); 47 } 48 mr=0;int ans=-1,ma=e[1],id,tmp; 49 for(int i=1;i<=nn;i++){ 50 int tmp=ma; 51 for(;i<=nn&&i<=tmp;i++) 52 ma=max(ma,e[i]); 53 ans++; 54 } 55 printf("%d\n",ans); 56 } 57 return 0; 58 }