【二分+hash】【manacher】【gfoj】Problem 852: antisymmetry

1 篇文章 0 订阅
1 篇文章 0 订阅

题目

定义字符串S为原串,SR为原串反转的到的字符串,SL为将原串中所有1变成0,0变成1得到的字符串。
一个非空字符串,对于他的每个第i个位置的字符和倒数第i个位置的字符都不同,那么这个串为antisymmetry。
特别的,如果一个字符串仅有0和1组成,那么当且仅当SL=SR的时候,他为antisymmetry。
对于一个长度为N的01串,我们需要确定这个01串中连续.非空.且满足antisymmetric的片段的数目。
不同的片段,对应相同的子串的情形也需要计数。

第一行输入一个整数N表示01串的长度
第二行输入一个长度为N的01串

40% 1<=n<=500
70% 1<=n<=5000
100% 1<=n<=500000

Output
输出一个整数表示antisymmetry串的数目

分析

根据数(xuan)学
我们可以发现对于随机数据暴力TLE的概率为 (1/2)250000
于是暴力A了
这里奉上两位dalao的写法

Orz orzgeotcbrl(hsz)

#include <cstdio>
#include <algorithm>
using namespace std;
#define N 500050
int n,i,j,p[N];
char s[N];
int main()
{
    scanf("%d",&n);
    scanf("%s",s);int ans=0;
    for (i=1;i<n;i++){
        if (j+p[j]>i) p[i]=min(j+p[j]-i,p[2*j-i]);
        while (i-p[i]-1>=0&&i+p[i]<n&&s[i-p[i]-1]!=s[i+p[i]]) p[i]++;ans+=p[i];
        if (i+p[i]>j+p[j]) j=i;
    }printf("%d\n",ans);
    return 0;
 } 

Orz lwn

#include <cstdio>
#include <algorithm>
#define M 1000000007
//#define M 998244353
#define DDF 2
//Deep♂Dark♂Fantasy
#define mid ((l+r+1) >> 1)
using namespace std;
int n,l,r,ans;
long long a[500050],f[500050],pre[500050],suf[500050];
char ch;
int main(){
    scanf("%d",&n);
    scanf("%c",&ch);
    for (int i=1;i<=n;i++) scanf("%c",&ch),a[i]=ch=='0'?-1:1;
    f[0]=1;
    for (int i=1;i<=n;i++) f[i]=f[i-1]*DDF % M; 
    for (int i=1;i<=n;i++) pre[i]=(pre[i-1]+a[i]*f[i-1]) % M;
    for (int i=n;i>=1;i--) suf[i]=(suf[i+1]+a[i]*f[n-i]) % M;
//  for (int i=1;i<=n;i++) printf("%d ",pre[i]);printf("\n");
//  for (int i=1;i<=n;i++) printf("%d ",suf[i]);printf("\n");
    for (int i=1;i< n;i++){
        for (l=0,r=min(i,n-i);l<r;){
            long long x=((pre[i+mid]  -pre[i]  )*f[n-i] % M+M) % M;
            long long y=((suf[i-mid+1]-suf[i+1])*f[i]   % M+M) % M;
            if (((x+y) % M)==0) l=mid;else r=mid-1;
        }
        ans+=l;
//      printf("%d\n",ans);
    }
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值