zoukankan      html  css  js  c++  java
  • SPOJ SUBST1

    题解参见罗穗骞的论文《后缀数组——处理字符串的有力工具》。

    最近开始重拾一些重点算法,比如网络流,强连通分量,还有后缀数组(字符串和数论相关一直都是弱项)。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <vector>
      5 #include <numeric>
      6 
      7 using LL = long long;
      8 
      9 const size_t maxN = 50000 + 10;
     10 
     11 char str[maxN];
     12 int sa[maxN], rank[maxN], height[maxN];
     13 size_t len;
     14 
     15 void input()
     16 {
     17     scanf("%s", str);
     18     len = strlen(str);
     19 }
     20 
     21 void buildSA()
     22 {
     23     struct Node {
     24         int k1, k2, id;
     25         bool operator == (const Node& rhs) const {
     26             return k1 == rhs.k1 && k2 == rhs.k2;
     27         }
     28     };
     29 
     30     std::vector<Node> node(len), temp(len);
     31     std::vector<int> bucketSize;
     32 
     33     for (int i = 0; i < len; i++)
     34         rank[i] = (int)str[i];
     35 
     36     auto radixSort = [&] (size_t alphaSize) -> void
     37     {
     38         bucketSize.resize(alphaSize);
     39         std::fill(bucketSize.begin(), bucketSize.end(), 0);
     40 
     41         for (auto& cur: node)
     42             bucketSize[cur.k2] += 1;
     43         std::partial_sum(bucketSize.begin(), bucketSize.end(), bucketSize.begin());
     44 
     45         for (auto it = node.crbegin(); it != node.crend(); ++it)
     46             temp[--bucketSize[it->k2]] = *it;
     47 
     48         std::fill(bucketSize.begin(), bucketSize.end(), 0);
     49 
     50         for (auto& cur: temp)
     51             bucketSize[cur.k1] += 1;
     52         std::partial_sum(bucketSize.begin(), bucketSize.end(), bucketSize.begin());
     53 
     54         for (auto it = temp.crbegin(); it != temp.crend(); ++it)
     55             node[--bucketSize[it->k1]] = *it;
     56     };
     57 
     58     for (size_t step = 0; step < len; step == 0 ? step = 1 : step <<= 1)
     59     {
     60         for (int i = 0; i < len; i++)
     61             node[i] = {rank[i], i + step < len ? rank[i + step] : 0, i};
     62 
     63         radixSort(step == 0 ? size_t(128) : len);
     64 
     65         int last = 1;
     66         rank[node[0].id] = 1;
     67         for (size_t i = 1; i < len; i++)
     68         {
     69             if (!(node[i] == node[i - 1]))
     70                 last += 1;
     71             rank[node[i].id] = last;
     72         }
     73 
     74         if (last == len)
     75             break;
     76     }
     77 
     78     for (int i = 0; i < len; i++)
     79         sa[rank[i] -= 1] = i;
     80 }
     81 
     82 void buildHeight()
     83 {
     84     height[0] = 0;
     85     int last = 0;
     86 
     87     for (int i = 0; i < len; i++)
     88     {
     89         if (rank[i] == 0)
     90             continue;
     91 
     92         int lp = sa[rank[i] - 1], cp = i;
     93         int cur = std::max(0, last - 1);
     94 
     95         for (; str[lp + cur] == str[cp + cur]; cur++) {}
     96         height[rank[i]] = last = cur;
     97     }
     98 }
     99 
    100 //#include <fmt/format.h>
    101 
    102 LL solve()
    103 {
    104     buildSA();
    105     buildHeight();
    106 
    107 //    for (int i = 0; i < len; i++)
    108 //        fmt::print("sa[{i}] = {1}, rank[{i}] = {2}, height[{i}] = {3}
    ",
    109 //                   fmt::arg("i", i), sa[i], rank[i], height[i]);
    110 
    111     LL ans = len - sa[0];
    112     for (int i = 1; i < len; i++)
    113         ans += (len - sa[i] - height[i]);
    114 
    115     return ans;
    116 }
    117 
    118 int main()
    119 {
    120     int T;
    121     for (scanf("%d", &T); T; T--)
    122     {
    123         input();
    124         printf("%lld
    ", solve());
    125     }
    126     return 0;
    127 }
  • 相关阅读:
    使用Distinct()内置方法对List集合的去重 问题
    TCP连接与HTTP请求
    ASP.NET MVC 使用 Authorize 属性过滤器验证用户是否已登录
    C#进阶系列——WebApi 跨域问题解决方案:CORS
    关于设计模式的六大原则
    C# WebApi 接口传参详解
    数据库数据流量太大-问题诊断
    docker的build生成镜像和启动container
    docker生成dotnet core镜像
    NET Core 源码浏览站点工具
  • 原文地址:https://www.cnblogs.com/Onlynagesha/p/8721547.html
Copyright © 2011-2022 走看看