码迷,mamicode.com
首页 > 其他好文 > 详细

hdu6230(求限制条件的回文个数,利用manacher+BIT求解)

时间:2020-10-21 20:33:08      阅读:23      评论:0      收藏:0      [点我收藏+]

标签:long   一个   范围   open   size   pid   code   hid   限制   

题:http://acm.hdu.edu.cn/showproblem.php?pid=6230

题意:求一个字符串中(长度<=5e5)中指定字符串个数;

   指定字符串约束为:类似俩个回文串“镶嵌”,设有俩个回文串的回文中心位置分别为x和y(x<y),前者的回文半径涵盖的范围必须包含y ,同时后者的回文半径要包含x;

分析:

   问题可以转化为这样的(x,y)的对数;

   也就是在x回文半径范围( x,x+rl[x] ]内有多少个位置y满足y-rl[y]<=x;

   在处理时,维护以x的约束条件“y-rl[y]>x”的单调队列,单调队列过程中持续加上(x,x+rl[x] ]间的贡献 

技术图片
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
#define pb push_back
const int inf=0x3f3f3f3f;
const ll INF=(1ll<<40);
const int M=1e6+6;
char s[M];
int rl[M],p[M];
struct BIT{
    ll tr[M];
    void init(){ memset(tr,0,sizeof(tr)); }
    void add(int x,ll c){
        for(int i=x;i<M;i+=i&-i) tr[i]+=c;
    }
    ll sum(int x){
        ll res=0;
        for(int i=x;i;i-=i&-i) res+=tr[i];
        return res;
    }
}bit;
///int evenrl[M];
void manacher(){
    int len=strlen(s);
    for(int i=len;i>=0;i--)
        s[i*2+1]=s[i],s[i*2]=#;
    int id,mx=0;
    int m=2*len+1;
    for(int i=1;i<m;i++){
        if(mx>i) p[i]=min(p[2*id-i],mx-i); else p[i]=1;
        while(s[i-p[i]]==s[i+p[i]]&&i-p[i]>=0&&i+p[i]<m)++p[i];
        if(i+p[i]>mx) id=i,mx=p[i]+i;
        if(s[i]!=#) rl[(i+1)/2]=(p[i]-1)/2;///奇数长的回文,长度不含回文中心
        ///else evenrl[(i+1)/2]=(p[i]-1)/2;///偶数长的回文,位置为左半部分末尾,长度为回文串的一半
    }
}
struct node{
    int val,id;
}a[M];

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%s",s);
        int n=strlen(s);
        bit.init();
        manacher();
        for(int i=1;i<=n;i++){
            a[i].id=i;
            a[i].val=i-rl[i];
        }
        sort(a+1,a+1+n,[&](node A,node B){
            return A.val<B.val;
        });
        int x=1;
        ll ans=0;
        for(int i=1;i<=n;i++){
            while(x<=n&&a[i].val>x){
                ans+=bit.sum(x+rl[x])-bit.sum(x);
                x++;
            }
            bit.add(a[i].id,1);
        }
        while(x<=n){
            ans+=bit.sum(x+rl[x])-bit.sum(x);
            x++;
        }
        printf("%lld\n",ans);

    }
    return 0;
}
View Code

 

hdu6230(求限制条件的回文个数,利用manacher+BIT求解)

标签:long   一个   范围   open   size   pid   code   hid   限制   

原文地址:https://www.cnblogs.com/starve/p/13849488.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!