zoukankan      html  css  js  c++  java
  • 反对称 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
    ",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;
    }
    
  • 相关阅读:
    修改mysql的时间/时区
    vue 3.0一些理解
    关于css中常用几种选择器的整理
    docker中MySQL8.0登录提示caching_sha2_password问题解决方法
    java请求url返回json
    weblogic11G 修改密码
    每天一个小知识
    出一套柠檬班测试开发视频(百度网盘)
    JAVA自动化,使用UIAutomator定位
    JAVA自动化,解决Appium无法输入中文问题
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11767007.html
Copyright © 2011-2022 走看看