BZOJ 2160: 拉拉队排练

Description

问长度前 (k) 大的奇长度回文子串的乘积.

Sol

Manacher.

直接马拉车跑一边,统计一下答案,每次将长度-2就可以了.

Code

/**************************************************************
    Problem: 2160
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:288 ms
    Memory:36456 kb
****************************************************************/
 
#include <cstdio>
#include <iostream>
using namespace std;
 
typedef long long LL;
const int N = 2000500;
const LL p = 19930726;
 
LL n,k,st,ans=1;
LL f[N],c[N];
char ch[N],s[N];
 
LL Pow(LL a,LL b,LL r=1) { for(;b;b>>=1,a=a*a%p) if(b&1) r=r*a%p;return r; }
int main() {
    cin>>n>>k;
    scanf("%s",s+1);
    s[0]='$';
     
    for(LL i=1,mx=0,j=0;i<=n;i++) {
        if(mx>i) f[i]=min(f[2*j-i],mx-i);else f[i]=1;
        for(;s[i+f[i]] == s[i-f[i]];f[i]++);
        if(i+f[i]>mx) mx=i+f[i],j=i;
    }
    for(int i=1;i<=n;i++) c[f[i]*2-1]++,st=max(st,f[i]*2-1);
     
//  for(int i=0;i<=n;i++) putchar(s[i]);cout<<endl;
//  for(int i=0;i<=n;i++) cout<<f[i]<<" ";cout<<endl;
//  for(int i=0;i<=st;i++) cout<<c[i]<<" ";cout<<endl;
     
    for(LL t;st;st--) {
        t=min(c[st],k);
        ans=(ans*Pow(st,t))%p;
        k-=t;
        if(st-2>0) c[st-2]+=c[st];
        if(!k) break;
    }
    if(k) puts("-1");
    else cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/beiyuoi/p/6198830.html