反对称 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;
}

原文地址:https://www.cnblogs.com/fangbozhen/p/11621842.html

时间: 2024-10-14 17:53:40

反对称 Antisymmetry的相关文章

【POI 2010】反对称 Antisymmetry

题目: 对于一个 $0/1$ 字符串,如果将这个字符串 $0$ 和 $1$ 取反后,再将整个串反过来和原串一样,就称作「反对称」字符串.比如 $00001111$ 和 $010101$ 就是反对称的,而 $1001$ 就不是.现在给出一个长度为 $n$ 的 $0/1$ 字符串,求它有多少个子串是反对称的,注意这里相同的子串出现在不同的位置会被重复计算. $n\le 5\times 10^5$ 分析: ①显然,反对称字符串的长度一定是偶数. 因为若不是偶数,中间的那个数取反永远不会等于自己. ②若

[家里蹲大学数学杂志]第066期南开大学2008年高等代数考研试题参考解答

1计算题 ($5\times 12'=60'$). (1)设 ${\bf A}\in \bbR^{n\times n}$ 适合 (a)$a_{ii}>0$, $i=1,2,\cdots,n$; (b)$a_{ij}<0$, $i\neq j$; (c)$\dps{\sum_{i=1}^n a_{ik}=0}$, $k=1,2,\cdots,n$. 试求 $\rank({\bf A})$. 解答: 写出 $$\bex {\bf A}&=&\sex{\ba{cccc} a_{11}

bzoj 2084: [Poi2010]Antisymmetry -- manacher

2084: [Poi2010]Antisymmetry Time Limit: 10 Sec  Memory Limit: 259 MB Description 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串.比如00001111和010101就是反对称的,1001就不是.现在给出一个长度为N的01字符串,求它有多少个子串是反对称的. Input 第一行一个正整数N (N <= 500,000).第二行一个长度为N的01字符串. Output

BZOJ 2084: [Poi2010]Antisymmetry

2084: [Poi2010]Antisymmetry Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 596  Solved: 379[Submit][Status][Discuss] Description 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串.比如00001111和010101就是反对称的,1001就不是.现在给出一个长度为N的01字符串,求它有多少个子串是反对称的. Input

bzoj2084【POI2010】Antisymmetry

2084: [Poi2010]Antisymmetry Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 432  Solved: 273 [Submit][Status][Discuss] Description 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作"反对称"字符串.比如00001111和010101就是反对称的,1001就不是. 现在给出一个长度为N的01字符串,求它有多少个子串是反对称

BZOJ2084: [Poi2010]Antisymmetry

2084: [Poi2010]Antisymmetry Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 187  Solved: 125[Submit][Status] Description 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串.比如00001111和010101就是反对称的,1001就不是.现在给出一个长度为N的01字符串,求它有多少个子串是反对称的. Input 第一行一个正整数

【BZOJ】【2084】【POI2010】Antisymmetry

Manacher算法 啊……Manacher修改一下就好啦~蛮水的…… Manacher原本是找首尾相同的子串,即回文串,我们这里是要找对应位置不同的“反回文串”(反对称?233) 长度为奇数的肯定不满足>_>(中间那个字符无论如何不反对称) 那么我们就找'#'为中心的即可…… 将判断条件a[i-p[i]-1]==a[i+p[i]+1]改成[不等……或是两个都是'#'] 将所有的p[i]加起来,即所有“反回文串”的长度加起来除以二就是答案啦~ 看代码吧>_< 1 /********

【bzoj2084】[Poi2010]Antisymmetry

2084: [Poi2010]Antisymmetry Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1205  Solved: 756[Submit][Status][Discuss] Description 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作"反对称"字符串.比如00001111和010101就是反对称的,1001就不是.现在给出一个长度为N的01字符串,求它有多少个子串是反对称的.

BZOJ 2084 [Poi2010]Antisymmetry(manacher)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2084 [题目大意] 对于一个01字符串,如果将这个字符串0和1取反后, 再将整个串反过来和原串一样,就称作“反对称”字符串. 比如00001111和010101就是反对称的,1001就不是. 现在给出一个长度为N的01字符串,求它有多少个子串是反对称的. [题解] 修改manacher的判定条件,对该串进行计算即可. [代码] #include <cstdio> #include