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;
    }
  • 相关阅读:
    Java多线程编程初识— —2
    Java多线程编程初识
    Java XML解析技术
    Java读取Properties文件的六种方法
    Java对象的序列化与反序列化
    文言写作
    阅读理解主题综合训练
    记叙文阅读的六大题型详解(全部转换成法事情人"法事情人")
    读书类、美景类作文
    开头技法
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5572256.html
Copyright © 2011-2022 走看看