参考资料这次是真抄的
1.后缀数组详解
2.后缀数组-学习笔记
3.后缀数组——处理字符串的有力工具

定义

\(SA\)排名为\(i\)的后缀的位置
\(rk\)位置为\(i\)的后缀的排名
\(tp\)第二关键字的排名为\(i\)的后缀的位置,还被用作\(rank\)的暂存
\(tax\)每个排名对应的后缀数量
后缀数组就是为了求出\(sa\)和\(rk\)

性质

\(rk[sa[i]]=i\) \(sa[rk[i]]=i\)

$LCP(x,y) $:字符串x与字符串y的最长公共前缀,在这里指x号后缀与与y号后缀的最长公共前缀

\(height[i]=lcp ( sa[i],sa[i - 1] )\),即排名为\(i\)的后缀与排名为\(i−1\)的后缀的最长公共前缀

\(H[i]:height[rak[i]]\),即\(i\)号后缀与它前一名的后缀的最长公共前缀

\(H[i] \geqslant H[i - 1] - 1\) 证明

$LCP(i,j)=LCP(j,i) $

\(LCP(i,i)=len(sa[i])=n-sa[i]+1\)

\(LCP(i,k)=min\left\{height[j] \right\}(i+1<=j<=k)\)

\(S\)不同的子串个数\(\dfrac{n(n+1)}{2} -\sum_{i=1}^nheight[i]\)

代码

#include <iostream>
#include <cstdio>
#include <string>
#define R register int

using namespace std;
const int N = 1000005;
string s;
/* sa[i]:排名为i的后缀的位置
rak[i]:从第i个位置开始的后缀的排名,下文为了叙述方便,把从第i个位置开始的后缀简称为后缀i
tp[i]:基数排序的第二关键字,意义与sa一样,即第二关键字排名为i的后缀的位置
tax[i]:i号元素出现了多少次。辅助基数排序
s:字符串,s[i]表示字符串中第i个字符串*/
int n, m, sa[N], rk[N], tp[N], c[N];
void _sort() {
    for(R i = 1; i <= m; ++i) c[i] = 0;
    for(R i = 1; i <= n; ++i) c[rk[i]]++;
    for(R i = 1; i <= m; ++i) c[i] += c[i - 1];
    for(R i = n; i >= 1; --i) sa[c[rk[tp[i]]]--] = tp[i];
}
void SA() {
    m = 150;
    for(R i = 1; i <= n; ++i) rk[i] = s[i - 1], tp[i] = i;
    _sort();
    for(R w = 1, p = 0; p < n && w <= n; m = p, w <<= 1) {
        p = 0;
        for(R i = 1; i <= w; ++i) tp[++p] = n - w + i;
        for(R i = 1; i <= n; ++i) if(sa[i] > w) tp[++p] = sa[i] - w;
        _sort();
        swap(tp, rk);
        rk[sa[1]] = p = 1;
        for(R i = 2; i <= n; ++i)
            rk[sa[i]] = (tp[sa[i - 1]] == tp[sa[i]] && tp[sa[i - 1] + w] == tp[sa[i] + w])
            ? p : ++p;
    }
}
/*i号后缀:从i开始的后缀
lcp(x,y):字符串x与字符串y的最长公共前缀,在这里指x号后缀与与y号后缀的最长公共前缀
height[i]:lcp(sa[i],sa[i?1]),即排名为i的后缀与排名为i?1的后缀的最长公共前缀
H[i]:height[rak[i]],即i号后缀与它前一名的后缀的最长公共前缀*/
int Height[N];
void Get() {
    int j, k = 0;
    for(int i = 1; i <= n; i++) {
        if(k) k--;
        j = sa[rk[i] - 1];
        while(s[i + k - 1] == s[j + k - 1]) ++k;
        Height[rk[i]] = k;
    }
}
int main()
{
    cin >> s;
    n = s.length();
    SA();
    for(R i = 1; i <= n; ++i) printf("%d ", sa[i]);
    cout << endl;
    Get();
    return 0;
}

Problem

P2408 不同子串个数

\(ans=\dfrac{n(n+1)}{2} -\sum height[i]\)

Luogu

P3809 【模板】后缀排序
P4070 [SDOI2016]生成魔咒
P3311 [SDOI2014]数数
P4051 [JSOI2007]字符加密
P2463 [SDOI2008]Sandy的卡片
P2408 不同子串个数

[笔记]后缀数组SA的更多相关文章

  1. 后缀数组SA学习笔记

    什么是后缀数组 后缀数组\(sa[i]\)表示字符串中字典序排名为\(i\)的后缀位置 \(rk[i]\)表示字符串中第\(i\)个后缀的字典序排名 举个例子: ababa a b a b a rk: ...

  2. 后缀数组(SA)总结

    后缀数组(SA)总结 这个东西鸽了好久了,今天补一下 概念 后缀数组\(SA\)是什么东西? 它是记录一个字符串每个后缀的字典序的数组 \(sa[i]\):表示排名为\(i\)的后缀是哪一个. \(r ...

  3. 后缀数组SA入门(史上最晦涩难懂的讲解)

    参考资料:victorique的博客(有一点锅无伤大雅,记得看评论区),$wzz$ 课件(快去$ftp$%%%),$oi-wiki$以及某个人的帮助(万分感谢!) 首先还是要说一句:我不知道为什么我这 ...

  4. bzoj3796(后缀数组)(SA四连)

    bzoj3796Mushroom追妹纸 题目描述 Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他从 ...

  5. 【字符串】后缀数组SA

    后缀数组 概念 实际上就是将一个字符串的所有后缀按照字典序排序 得到了两个数组 \(sa[i]\) 和 \(rk[i]\),其中 \(sa[i]\) 表示排名为 i 的后缀,\(rk[i]\) 表示后 ...

  6. 浅谈后缀数组SA

    这篇博客不打算讲多么详细,网上关于后缀数组的blog比我讲的好多了,这一篇博客我是为自己加深印象写的. 给你们分享了那么多,容我自私一回吧~ 参考资料:这位dalao的blog 一.关于求Suffix ...

  7. 后缀数组SA

    复杂度:O(nlogn) 注:从0到n-1 const int maxn=1e5; char s[maxn]; int sa[maxn],Rank[maxn],height[maxn],rmq[max ...

  8. 洛谷2408不同字串个数/SPOJ 694/705 (后缀数组SA)

    真是一个三倍经验好题啊. 我们来观察这个题目,首先如果直接整体计算,怕是不太好计算. 首先,我们可以将每个子串都看成一个后缀的的前缀.那我们就可以考虑一个一个后缀来计算了. 为了方便起见,我们选择按照 ...

  9. 洛谷4248 AHOI2013差异 (后缀数组SA+单调栈)

    补博客! 首先我们观察题目中给的那个求\(ans\)的方法,其实前两项没什么用处,直接\(for\)一遍就求得了 for (int i=1;i<=n;i++) ans=ans+i*(n-1); ...

随机推荐

  1. Django 学习笔记(五) --- Ajax 传输数据

    人生苦短 ~ Tips:仅适用于 Python 3+(反正差别不大,py2 改改也能用).因为据 Python 之父 Guido van Rossum 说会在 2020 年停止对 Python 2 的 ...

  2. [HAOI 2015]按位或

    Description 题库链接 刚开始你有一个数字 \(0\) ,每一秒钟你会随机选择一个 \([0,2^n-1]\) 的数字,与你手上的数字进行或( \(\text{or}\) )操作.选择数字 ...

  3. Apollo 4 客户端 SDK 设计

    前言 之前聊了客户端的一些功能,例如融入 Spring, @value 注解的自动刷新实现,长轮询等,这次从客户端的整体设计来聊聊. 设计 上图是 client 项目的包结构. 其中,核心包就是 in ...

  4. [转]group by 后使用 rollup 子句总结

    group by 后使用 rollup 子句总结 一.如何理解group by 后带 rollup 子句所产生的效果 group by 后带 rollup 子句的功能可以理解为:先按一定的规则产生多种 ...

  5. C++注入记事本

    #include <iostream>; using namespace std; #include <windows.h>; #include <tlhelp32.h& ...

  6. SQLServer删除登录记录用户名和密码

    介绍: 作为一名开发人员都会知道我们做的项目都要用到数据库,数据库都需要账号和密码,然而问题来了,做的东西多了那些没用的账号和密码还在哪里纠缠着我们.所有我们不能忍了删除掉他. 网上很多都是2008的 ...

  7. CSS--使用伪选择器制作箭头图标

    // 使用Transform的属性,组合translate(位移)和rotate(旋转),将生成的小矩形组合成各种箭头样式: HTML <section class="main&quo ...

  8. Breeze 部署 Kubernetes 1.12.1高可用集群

    今天看文章介绍了一个开源部署 K8S 的工具,有空研究下~ Github 地址: https://github.com/wise2c-devops/breeze

  9. 2017-11-26 编程语言试验之Antlr4+Java实现"圈2"

    "中文编程"知乎专栏原文 此文涉及的源码版本: program-in-chinese/quan2 声明 代码来源 How to Create Language Using Antl ...

  10. 获取子元素节点(children,childNodes)

    在js中获取元素节点有DOM对应的方法如getElementsByTagName()等等..对于获取子元素还有另外一种获取方法ChildNodes 不过ChidNodes在高级浏览器除(IE6-8)里 ...