HDU 6230 Palindrome (manacher+树状数组)

题意

给你一个1e5的字符串,让你求出子串的数量,使得子串满足:
长度为\(3n-2\),且\([1,2n-1]\)\([n,3n-2]\)都是回文串

思路

可以看出,这两个回文串长度都是奇数
我们先用马拉车处理出每个字符\(s[i]\)可以左右扩展的最长长度\(a[i]\)
我们找的就是找\((i,j)\)的对数\((i<j)\),使得:
\(i+a[i]\geq j\)\(j-a[j] \leq i\)

处理方式有以下几种

  • 由第二个不等式可以将满足条件的\(j\)放入bit中,每次枚举\(i\)的时候查询\([i,i+a[i]]\)的和
  • 按照\(a[i]\)从大到小排序,每次在BIT中将\(i\)加一,答案就是每次在\(a[i]\)影响范围内的和

代码

这是第二种处理方式

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional>
    
#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
 
using namespace std;
 
typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;
typedef pair<ll,int> PIL;
 
const db eps = 1e-6;
const int mod = 1e9+7;
const int maxn = 2e6+100;
const int maxm = 2e6+100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);


int t;
int n;
int a[maxn];
char s[maxn];
char ma[maxn*2];
int mp[maxn*2];
void manacher(char s[], int len){
    int l = 0;
    ma[l++]='$';ma[l++]='#';
    for(int i = 0; i < len; i++){
        ma[l++]=s[i];ma[l++]='#';
    }
    ma[l]=0;
    int mx = 0,id=0;
    for(int i = 0; i < l; i++){
        mp[i]=mx>i?min(mp[2*id-i],mx-i):1;
        while(ma[i+mp[i]]==ma[i-mp[i]])mp[i]++;
        if(i+mp[i]>mx){
            mx=i+mp[i];id=i;
        }
    }
}
int len;
ll tree[maxn];
int lowbit(int x){return x&-x;}
void add(int x ,int c){
    for(int i = x; i <= len; i+=lowbit(i))tree[i]+=c;
}
ll sum(int x){
    ll ans = 0;
    for(int i = x; i; i-=lowbit(i))ans+=tree[i];
    return ans;
}
struct node{
    int l,r,id,len;
    node(){}
    node(int l, int r, int id, int len):l(l),r(r),id(id),len(len){}
};
bool cmp(node a, node b){return a.len>b.len;}
vector<node>v;
int main(){
    scanf("%d", &t);
    while(t--){
        v.clear();
        scanf("%s",s);
        len = strlen(s);
        for(int i = 0; i <= len; i++)tree[i]=0;
        manacher(s,len);
        for(int i = 0; i< 2*len+2; i++){
            if(i&&i%2==0){
                a[i/2]=(mp[i]-1)/2;
                int len = a[i/2];
                v.pb(node(i/2-len,i/2+len,i/2,len));
            }
        }

        sort(v.begin(),v.end(),cmp);
        ll ans = 0;
        for(int i = 1; i <= len; i++){
            ans+=1ll*(sum(v[i-1].r)-sum(v[i-1].l-1));
            add(v[i-1].id,1);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
/*
 */
posted @ 2019-10-30 15:52  wrjlinkkkkkk  阅读(212)  评论(0编辑  收藏  举报