回文子串Manacher算法模板

r[i]是处理后每个字符的回文半径
r[i]-1即为处理前回文子串长度
P3805 【模板】manacher算法

#include<iostream>
#include<cstdio>
using namespace std;
const int P=19930726;
typedef long long LL;
char str[2000005];
int r[2000005],a[1000005];
LL sum[1000005];
int n,len;
LL k,ans=1;
void fast_pow(LL base,LL x) {
    base%=P;
    while (x>0) {
        if (x&1) ans=ans*base%P;
        base=base*base%P;
        x>>=1;
    }
}
void read() {
    char ch;
    len=1;str[1]='#';
    while (ch<'a'||ch>'z') ch=getchar();
    while (ch<='z'&&ch>='a') {
        str[++len]=ch;
        str[++len]='#';//避免奇偶性讨论
        ch=getchar();
    }
    str[0]='$';str[len+1]='@';//防止下标越界
}
void manacher() {
    int p=0,mx=0;
    for (int i=1;i<=len;i++) {
        if (mx>i) r[i]=min(r[2*p-i],mx-i);
        else r[i]=1;
        while (str[i+r[i]]==str[i-r[i]]) r[i]++;
        if (i+r[i]>mx) p=i,mx=i+r[i];
    }
}
int main() {
    scanf("%d%lld",&n,&k);
    read();
    manacher();
    for (int i=2;i<len;i+=2) a[1]++,a[r[i]]--;
    for (int i=1;i<=(len>>1);i++) sum[i]=sum[i-1]+a[i];
    if (!(n&1)) n--;
    for (int i=n;i>0;i-=2) {
        if (!sum[i]) continue;
        LL tmp=min(k,sum[i]);
        fast_pow(i,tmp);
        k-=tmp;
        if (k<=0) break;
    }
    if (k>0) cout<<-1;
    else printf("%lld",ans);
    return 0;
}

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/u014304190/article/details/79594010