zoukankan      html  css  js  c++  java
  • [HDU3518]Boring counting(后缀数组)

    传送门

    求出现超过1次的不重叠子串的个数

    根据论文中的方法。

    枚举子串的长度 k。

    用 k 给 height 数组分组,每一组求解,看看当前组的位置最靠后的后缀和位置最靠前的后缀所差个数是否大于长度,大于的话 ans++。

    分组思想需要认真体会一下。

    ——代码

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #define N 1005
     5 #define max(x, y) ((x) > (y) ? (x) : (y))
     6 #define min(x, y) ((x) < (y) ? (x) : (y))
     7 
     8 int len, n, m, ans;
     9 int buc[N], x[N], y[N], sa[N], ran[N], height[N];
    10 char s[N];
    11 
    12 inline void build_sa()
    13 {
    14     int i, k, p;
    15     for(i = 0; i < m; i++) buc[i] = 0;
    16     for(i = 0; i < len; i++) buc[x[i] = s[i]]++;
    17     for(i = 1; i < m; i++) buc[i] += buc[i - 1];
    18     for(i = len - 1; i >= 0; i--) sa[--buc[x[i]]] = i;
    19     for(k = 1; k <= len; k <<= 1)
    20     {
    21         p = 0;
    22         for(i = len - 1; i >= len - k; i--) y[p++] = i;
    23         for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
    24         for(i = 0; i < m; i++) buc[i] = 0;
    25         for(i = 0; i < len; i++) buc[x[y[i]]]++;
    26         for(i = 1; i < m; i++) buc[i] += buc[i - 1];
    27         for(i = len - 1; i >= 0; i--) sa[--buc[x[y[i]]]] = y[i];
    28         std::swap(x, y);
    29         p = 1, x[sa[0]] = 0;
    30         for(i = 1; i < len; i++)
    31             x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
    32         if(p >= len) break;
    33         m = p;
    34     }
    35 }
    36 
    37 inline void build_height()
    38 {
    39     int i, j, k = 0;
    40     for(i = 0; i < len; i++) ran[sa[i]] = i;
    41     for(i = 0; i < len; i++)
    42     {
    43         if(!ran[i]) continue;
    44         if(k) k--;
    45         j = sa[ran[i] - 1];
    46         while(s[i + k] == s[j + k] && i + k < len && j + k < len) k++;
    47         height[ran[i]] = k;
    48     }
    49 }
    50 
    51 inline void check(int k)
    52 {
    53     int Max, Min;
    54     Max = Min = sa[0];
    55     for(int i = 1; i < len; i++)
    56         if(height[i] >= k)
    57         {
    58             Max = max(Max, sa[i]);
    59             Min = min(Min, sa[i]);
    60         }
    61         else
    62         {
    63             ans += Max - Min >= k;
    64             Max = Min = sa[i];
    65         }
    66     ans += Max - Min >= k;
    67 }
    68 
    69 int main()
    70 {
    71     while(scanf("%s", s) != EOF)
    72     {
    73         if(s[0] == '#') break;
    74         len = strlen(s);
    75         m = 300;
    76         build_sa();
    77         build_height();
    78         ans = 0;
    79         for(int i = 1; i <= (len >> 1); i++) check(i);
    80         printf("%d
    ", ans);
    81     }
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    socket实现一个简单的echo服务
    Netty实现丢弃服务协议(Netty4.X学习一)
    大型情感剧集Selenium:8_selenium网页截图的四种方法
    python原类、类的创建过程与方法
    Flask使用bootstrap为HttpServer添加上传文件功能
    充满含金量的一场云原生Meetup,入场券免费发送中……
    Hadoop伪分布式集群的安装部署
    从缓冲池命中率角度判断自己的MYSQL数据库是否需要扩容内存
    MySQL分区表概述
    如何防止mysql数据库被勒索
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6984169.html
Copyright © 2011-2022 走看看