1. 程式人生 > >【[POI2010]ANT-Antisymmetry】

【[POI2010]ANT-Antisymmetry】

開始複習字串了

第一步肯定得是\(hash\)

首先理性分析一波不可能出現長度為奇數的反迴文串,對稱軸位置取反之後肯定和原來不相等了

我們可以列舉所有迴文串的對稱中心,之後我們發現這個樣子是具有單調性de

於是我們就利用\(hash\)來判斷

將原來的串取反之後在反轉,判斷在對稱中心左右兩邊二分的長度是否相等就可以啦

程式碼

#include<iostream>
#include<cstdio>
#include<cstring>
#define re register
#define ull unsigned long long
#define maxn 500005
#define min(a,b) ((a)<(b)?(a):(b))
char S[maxn],T[maxn];
int a[maxn],b[maxn];
int n;
ull ha[maxn],sh[maxn];
ull pow[maxn];
ull base=17;
long long num;
inline ull get_hash(int l,int r,int op)
{
    if(!op) return ha[r]-ha[l-1]*pow[r-l+1];
    return sh[n-l+1]-sh[n-r]*pow[r-l+1];
}
int main()
{
    scanf("%d",&n);
    scanf("%s",S+1);
    for(re int i=1;i<=n;i++)
        if(S[i]=='0') a[i]=0;
            else a[i]=1;
    pow[0]=1;
    for(re int i=1;i<=n;i++)
        pow[i]=pow[i-1]*base;
    for(re int i=1;i<=n;i++)
        ha[i]=ha[i-1]*base+(a[i]+1);
    for(re int i=1;i<=n;i++)
        b[i]=a[n-i+1]^1;
    for(re int i=1;i<=n;i++)
        sh[i]=sh[i-1]*base+(b[i]+1);
    for(re int i=1;i<n;i++)
    {
        int l=1,r=min(i,n-i);
        int ans=0;
        while(l<=r)
        {
            int mid=l+r>>1;
            if(get_hash(i-mid+1,i,1)==get_hash(i+1,i+mid,0)) l=mid+1,ans=mid;
            else r=mid-1;
        }
        num+=ans;
    }
    printf("%lld\n",num);
    return 0;
}
/*
8
11001011
*/