反对称 Antisymmetry

Posted fangbozhen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反对称 Antisymmetry相关的知识,希望对你有一定的参考价值。

https://loj.ac/problem/2452

题目描述

  反对称串定义为进行0、1取反后再反过来和原串相同的字符串,给出一个字符串,求它的多少个子串是反对称串。

思路

  首先我们从反对称串的定义入手,我们考虑如果一个串S为反对称串,显然它的长度是偶数,那么它也就是以它的对称轴为分割后将其前一部分反转后对称的字符串。因此,转化定义后我们的字符串具有单调性,即若一个字符串为反对称串,那么我们删除首尾后它仍是反对称串。所以我们可以暴力枚举每一个点为对称轴,二分查找其为反对称串的位置,对答案+找到最大反对称串长度的一半,二反对称串的判定可以用字符串Hash实现O(1)判断。

代码

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const ull p=47;
char s[500005];
ull power[500005],sum1[500005],sum2[500005];
ull f_hash(ull k,ull n,bool f)

    if(f)return sum1[k]-sum1[k-n]*power[n];
    else return sum2[k]-sum2[k+n]*power[n];

ull check(ull pos,ull len)

    if(s[pos]==s[pos+1])return 0;
    ull l=1,r=len;
    while(l<=r)
    
        ull mid=l+r>>1;
        if(f_hash(pos,mid,1)==f_hash(pos+1,mid,0))l=mid+1;
        else r=mid-1;
    
    return r;

int main() 

    int n;
    scanf("%d",&n);
    scanf(" %s",s+1);
    power[0]=1;
    for(int i=1;i<=n;i++)
    
        sum1[i]=sum1[i-1]*p+s[i];
        power[i]=power[i-1]*p;
    
    for(int i=n;i>=1;i--)
        sum2[i]=sum2[i+1]*p+(1-s[i]+0);
//    for(int i=1;i<=n;i++)
//        printf("%llu %llu %llu\n",sum1[i],sum2[i],power[i]);
    ull ans=0;
    for(ull i=1;i<n;i++)
        ans+=check(i,min(i,n-i));
    printf("%llu",ans);
    return 0;

 

以上是关于反对称 Antisymmetry的主要内容,如果未能解决你的问题,请参考以下文章

[Poi2010]Antisymmetry

Poi2010 Antisymmetry

[POI2010] Antisymmetry

bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp)

bzoj 2084: [Poi2010]Antisymmetry -- manacher

BZOJ 2084 [Poi2010]Antisymmetry(manacher)