• 【BZOJ】【2084】【POI2010】Antisymmetry


    Manacher算法


      啊……Manacher修改一下就好啦~蛮水的……

      Manacher原本是找首尾相同的子串,即回文串,我们这里是要找对应位置不同的“反回文串”(反对称?233)

      长度为奇数的肯定不满足>_>(中间那个字符无论如何不反对称)

      那么我们就找'#'为中心的即可……

      将判断条件a[i-p[i]-1]==a[i+p[i]+1]改成【不等……或是两个都是'#'】

      将所有的p[i]加起来,即所有“反回文串”的长度加起来除以二就是答案啦~

      看代码吧>_<

     1 /**************************************************************
     2     Problem: 2084
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:68 ms
     7     Memory:9572 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 2084
    11 #include<vector>
    12 #include<cstdio>
    13 #include<cstring>
    14 #include<cstdlib>
    15 #include<iostream>
    16 #include<algorithm>
    17 #define rep(i,n) for(int i=0;i<n;++i)
    18 #define F(i,j,n) for(int i=j;i<=n;++i)
    19 #define D(i,j,n) for(int i=j;i>=n;--i)
    20 #define pb push_back
    21 using namespace std;
    22 typedef long long LL;
    23 inline int getint(){
    24     int r=1,v=0; char ch=getchar();
    25     for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1;
    26     for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0';
    27     return r*v;
    28 }
    29 const int N=5e5+10,INF=~0u>>2;
    30 /*******************template********************/
    31 char s[N];
    32 int a[N<<1],p[N<<1];
    33 int main(){
    34     int n=getint();
    35     scanf("%s",s);
    36     F(i,1,n) a[i<<1]=s[i-1];
    37     n=n<<1|1;
    38     int id=0,ans=0;
    39     F(i,1,n){
    40         if (a[i]!=0) continue;
    41         if (p[id]+id>i) p[i]=min(p[2*id-i],p[id]+id-i);
    42         else p[i]=0;
    43         while(i-p[i]-1>0 && i+p[i]+1<=n &&
    44             (a[i-p[i]-1]!=a[i+p[i]+1] || a[i-p[i]-1]==0))p[i]++;
    45         if (p[i]+i>p[id]+id) id=i;
    46         ans+=p[i];
    47     }
    48     printf("%d
    ",ans/2);
    49     return 0;
    50 }
    View Code

    2084: [Poi2010]Antisymmetry

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 247  Solved: 162
    [Submit][Status][Discuss]

    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

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    SVN资料库转移-----dump和load
    windows Server 2003修改远程连接限制
    oracle定时任务
    Oacle常用语句
    决策树
    Logistic回归
    Matplotlab绘图基础
    基本术语
    看懂执行并优化
    数据分析方法论
  • 原文地址:https://www.cnblogs.com/Tunix/p/4398825.html
Copyright © 2020-2023  润新知