zoukankan      html  css  js  c++  java
  • Hihocoder #1602 : 本质不同的回文子串的数量 manacher + BKDRhash

    #1602 : 本质不同的回文子串的数量

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    给定一个字符串S,请统计S的所有子串中,有多少个本质不同的回文字符串?

    注意如果两个位置不同的子串满足长度相同且对应字符也都相同,则认为这两个子串本质上是相同的。

    输入

    一个只包含小写字母的字符串S。

    对于30%的数据,S长度不超过100。

    对于60%的数据,S长度不超过1000。

    对于100%的数据,S长度不超过800000。

    输出

    回文子串的数量

    样例输入
    abbab
    样例输出
    5
    题解:
      跑manacher的时候 hash标记即可
    #include <bits/stdc++.h>
    inline long long read(){long long x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
    using namespace std;
    
    const long long INF = 1e14;
    const int N = 1e6 + 7;
    
    unsigned long long P = 10000019ULL;
    unsigned long long sqr[N],has[N];
    
    //BKDRHash,最优的字符串hash算法。hash一开始是等于0的
    const int seed = 13131; // 31 131 1313 13131 131313 etc..
    const int maxn = 2000000+10;
    char str[maxn];
    unsigned long long sumHash[maxn]; //前缀hash值
    const int MOD = 2000007;
    struct StringHash
    {
        int first[MOD+2],num;
        unsigned long long EdgeNum[maxn]; // 表明第i条边放的数字(就是sumHash那个数字)
        int next[maxn],close[maxn]; //close[i]表示与第i条边所放权值相同的开始的最大位置
        //就比如baba,现在枚举长度是2,开始的时候ba,close[1] = 1;表明"ba"开始最大位置是从1开始
        //然后枚举到下一个ba的时候,close[1]就要变成3了,开始位置从3开始了
        void init ()
        {
            num = 0; memset (first,0,sizeof first);
            return ;
        }
        int insert (unsigned long long val,int id) //id是用来改变close[]的
        {
            int u = val % MOD;
            for (int i = first[u]; i ; i = next[i]) //存在边不代表出现过,出现过要用val判断,val才是唯一的,边还是压缩后(%MOD)的呢
            {
                if (val == EdgeNum[i]) //出现过了
                {
                    int t = close[i]; close[i] = id;//更新最大位置
                    return t;
                }
            }
            ++num; //没出现过的话,就加入图吧
            EdgeNum[num] = val; // 这个才是精确的
            close[num] = id;
            next[num] = first[u];
            first[u] = num;
            return 0;//没出现过
        }
    }H;
    
    char a[N];
    int ans = 0;
    map<unsigned long long, int> mp;
    void gao(int i,int j) {
        unsigned long long now = has[j] - has[i-1] * sqr[j-i+1];
        if(!H.insert(now,1)) ++ans,mp[now]++;
    }
    int r[N];
    int main() {
        scanf("%s",a+1);
        int n = strlen(a+1);
        sqr[0] = 1;for(int i = 1; i <= n; ++i) sqr[i] = sqr[i-1] * P;
        for(int i = 1; i <= n; ++i) has[i] = has[i-1] * P + a[i];
        int x = 0, p = 0;
        for(int i = 1; i <= n; ++i) {
            int j = 0;
            gao(i,i);
            if(p > i) j = min(r[2*x-i],p-i);
            while(i + j + 1 <= n&& a[i+j+1] == a[i-j-1])
            {
                gao(i-j-1,i+j+1);
                j++;
            }
            r[i] = j;
            if(i+j > p) {
                p = i + j;
                x = i;
            }
        }
        H.init();
        x = 0,p = 0;
        for(int i = 2; i <= n; ++i) {
            int j = 0;
            if(p > i) j = min(r[2*x-i],p-i+1);
            while(i+j<=n && a[i+j] == a[i-j-1]) {
                gao(i-j-1,i+j);
                ++j;
            }
            r[i] = j;
            if(i+j-1 > p) {
                p = i+j-1;
                x = i;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Android Gradle Plugin指南(五)——Build Variants(构建变种版本号)
    文件内容操作篇clearerr fclose fdopen feof fflush fgetc fgets fileno fopen fputc fputs fread freopen fseek ftell fwrite getc getchar gets
    文件操作篇 close creat dup dup2 fcntl flock fsync lseek mkstemp open read sync write
    嵌入式linux应用程序调试方法
    version control system:git/hg/subversion/cvs/clearcase/vss。software configruation management。代码集成CI:Cruisecontrol/hudson/buildbot
    最值得你所关注的10个C语言开源项目
    如何记录linux终端下的操作日志
    CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能
    sizeof, strlen区别
    C/C++嵌入式开发面试题
  • 原文地址:https://www.cnblogs.com/zxhl/p/7629204.html
Copyright © 2011-2022 走看看