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

一个正整数,表示反对称子串的个数。

Sample Input

8
11001011

Sample Output

7

hint
7个反对称子串分别是:01(出现两次), 10(出现两次), 0101, 1100和001011

HINT

#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1000100
int n,p[N],mx,md,len;
string s;
char c[N];
ll ans;
inline bool ck(int x)
{
    if(c[x+p[x]]!=c[x-p[x]]) return (c[x+p[x]]-‘0‘)+(c[x-p[x]]-‘0‘)==1;
    return c[x+p[x]]==‘#‘;
}
int main()
{
    scanf("%d",&n);
    cin>>s;
    c[0]=‘&‘;
    for(int i=0;i<=n;i++)
    {
        c[i<<1|1]=‘#‘;
        c[(i<<1)+2]=s[i];
    }
    len=(n<<1)+2;
    for(int i=1;i<len;i++)
    {
        p[i]=mx>i?min(p[(md<<1)-i],mx-i):1;
        for(;ck(i);p[i]++);
        if((i&1)&&p[i]+i>mx)
        {
            mx=p[i]+i;
            md=i;
        }
        if(i&1) ans+=(p[i]-1)>>1;
    }
    printf("%lld\n",ans);
    return 0;
}
时间: 2024-10-12 19:51:55

bzoj 2084: [Poi2010]Antisymmetry -- manacher的相关文章

BZOJ 2084 Poi2010 Antisymmetry Manacher算法

题目大意:给定一个长度为n的01串,问有多少个子串满足翻转并取反后和原来一样 定义0=1,0≠0,1≠1,跑Manacher即可 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 500500 using namespace std; int n; char s[M]; long long Manacher(char str[],in

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

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

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 第一行一个正整数

【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 二分+hash OR Manacher

思路: 二分+哈希 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N=500050; const ll mod=1000000007; int n; ll hs1[N],hs2[N],base[N],Ans; char s1[N],s2[N]; int main(){

bzoj 2084

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2084 这道题很容易想到就是一个变种的最长回文字串, 不过回文的规则变成了s[i + p[i]] + s[i - p[i]] == 1 可以用hash 来nlogn, 不过最优是用manacher, 然后有一个非常迷的查空位的方法(' '       ) 可以看代码 #include <iostream> #include <cstring> #include <algo

单调队列 BZOJ 2096 [Poi2010]Pilots

2096: [Poi2010]Pilots Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 819  Solved: 418[Submit][Status][Discuss] Description Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值.耍畸形一个人是不行的,于是他找到了你. Input 输入:第一行两个有空格隔开的整数k(0

BZOJ 2086: [Poi2010]Blocks

2086: [Poi2010]Blocks Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 494  Solved: 222[Submit][Status][Discuss] Description 给出N个正整数a[1..N],再给出一个正整数k,现在可以进行如下操作:每次选择一个大于k的正整数a[i],将a[i]减去1,选择a[i-1]或a[i+1]中的一个加上1.经过一定次数的操作后,问最大能够选出多长的一个连续子序列,使得这个子序列的每个数