codeforces 159D Palindrome pairs 【manacher+递推】

本文介绍了一种使用Manacher算法求解字符串中不覆盖的回文串对数的方法。通过预处理得到回文串长度的序列,再利用前缀和技巧,高效计算所有可能的回文串对数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://codeforces.com/problemset/problem/159/D

/*
题目大意:求一个字符串内不覆盖的回文串对数;

思路;首先可以用manacher求出一个p 序列,记录的是以当前字母为中心是回文串的长度,然后求一
      下包括当前字母前面的字母形成回文串的总数(前缀和),包括后面的字母利用了前面的字母
      形成的回文穿。
      举个列子:aabaa  manacher转换后的字符串应为 # a # a # b # a # a
                                       前缀和就是 0 3 3 5 5 6 6 8 8 9
                                       下标       1 2 3 4 5 6 7 8 9 10
      最后枚举每个回文串右端的回文串个数相加就是答案;
      具体可以看代码 (^ω^)
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=2e4+10;

char str[N];
ll p[N],sum[N];

int main()
{
    scanf("%s",str);
    int len=strlen(str),id=0;
    for(int i=len; i>=0; i--)
    {
        str[i*2+2]=str[i];
        str[i*2+1]='#';
    }
    str[0]='*';
    for(int i=2; i<=len*2; ++i)
    {
        if(p[id]+id>i) p[i]=p[2*id-i]>p[id]+id-i?p[id]+id-i:p[2*id-i];
        else p[i]=1;
        while(str[i-p[i]]==str[i+p[i]]) p[i]++;
        if(id+p[id]<i+p[i]) id=i;
    }
    for(int i=1; i<=len*2; ++i)
    {
        if(i&1)
            for(int j=1; j<p[i]; j+=2)
                sum[i-j]++;
        else
            for(int j=0; j<p[i]; j+=2)
                sum[i-j]++;
    }
    for(int i=1;i<=len*2;++i) sum[i]+=sum[i-1];
    for(int i=1;i<=len*2;++i) printf("%lld ",sum[i]); printf("\n");
    ll ans=0;
    for(int i=1; i<=len*2; ++i)
    {
        if(i&1)
            for(int j=1; j<p[i]; j+=2)
                ans+=sum[len*2]-sum[i+j];
        else
            for(int j=0; j<p[i]; j+=2)
                ans+=sum[len*2]-sum[i+j];
    }
    printf("%lld\n",ans);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值