zoukankan      html  css  js  c++  java
  • hdu6230(求限制条件的回文个数,利用manacher+BIT求解)

    题: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
    ",ans);
    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    swoole入门abc
    PHP实现定时任务(非linux-shell方式,与操作系统无关)
    PHP经典算法题
    lumen使用CORS解决跨域问题
    轻松搞定 JS 的this、call和apply
    Nginx与PHP工作原理
    PHP的cURL扩展库使用详解
    PHP 中的 cURL 爬虫实战基础
    jvm误区--动态对象年龄判定
    从源码分析如何优雅的使用 Kafka 生产者
  • 原文地址:https://www.cnblogs.com/starve/p/13849488.html
Copyright © 2011-2022 走看看