zoukankan      html  css  js  c++  java
  • bzoj3067 Hyperdrome

    Description

    给定一个字符串,由大小写字母组成。长度为N,1<=N<3*10^5 问其有多少个子串,这些子串本身是个回文串,或者其中的字符经过重组合后 也可以为回文串.

    将每个不同字母随机分配一个非零值,并保证这些值之间在异或意义下线性无关

    一个子串可以重排为回文串当且仅当串中字母对应的值的异或和为 0(所有字母出现偶数次)或某个字母对应的值(这个字母出现奇数次,其余字母出现偶数次)

    处理出前缀和并用一个hashmap(散列函数不要用取模否则可能tle)维护在当前位置以前每个前缀和值出现了几次,扫一遍记录答案

    时间复杂度O(52n)

    #include<cstdio>
    #include<cstdlib>
    typedef unsigned long long u64;
    const int P=4194304;
    u64 X[P];
    int t[P];
    int n;
    char s[300010];
    u64 v=0,ans=0,h[256],hs[64];
    char cs[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int find(u64 x){
        int w=x&4194303;
        while(t[w]){
            if(X[w]==x)return t[w];
            w+=123457;
            if(w>=P)w-=P;
        }
        return 0;
    }
    void ins(u64 x){
        int w=x&4194303;
        while(t[w]){
            if(X[w]==x){
                ++t[w];
                return;
            }
            w+=123457;
            if(w>=P)w-=P;
        }
        X[w]=x;t[w]=1;
    }
    int main(){
        srand(29399);
        for(int i=0;i<52;i++){
            h[cs[i]]=1ull<<i;
            for(int j=0;j<i;j++)if(rand()&1)h[cs[i]]^=1ull<<j;
            hs[i]=h[cs[i]];
        }
        scanf("%d%s",&n,s+1);
        ins(0);
        for(int i=1;i<=n;i++){
            v^=h[s[i]];
            ans+=find(v);
            for(int i=0;i<52;i++)ans+=find(v^hs[i]);
            ins(v);
        }
        printf("%llu
    ",ans);
        return 0;
    }
  • 相关阅读:
    Python基础-16生成器-迭代器
    Python基础-15模块-包-库
    Python基础-14异常处理
    Python基础-13面向对象
    Python基础-12解析式
    Python 入门日记(十)—— 文件和异常
    Python 入门日记(九)—— 类
    Python 入门日记(八)—— 函数
    Python 入门日记(七)—— 用户输入和 while 循环
    Python 入门日记(六)—— 字典
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5572256.html
Copyright © 2011-2022 走看看