首页 > 其他分享 >后缀数组(SA)做题记录

后缀数组(SA)做题记录

时间:2023-08-01 21:34:27浏览次数:39  
标签:ch 后缀 int 数组 -- SA sa

SA 真的是个好东西,好呀好东西。

基础定义:

$sa$ 数组:后缀排序后排名为 $i$ 的后缀的起始位置下标。

$rk$ 数组:起始下标为 $i$ 的后缀的排名。

$height$ 数组:后缀排序后排名为 $i$ 和 $i-1$ 的最长公共前缀长度(Lcp)

模板:(小bug:在SA代码

char ch[N];
struct Suffix_Array
{
    ll m=200,X[N],Y[N],c[N],num[N],sa[N],height[N],rk[N],lg[N],st[N][23];
    void Sa()
    {
        for(int i=1;i<=n;i++)X[i]=ch[i],c[X[i]]++;
        for(int i=2;i<=m;i++)c[i]+=c[i-1];
        for(int i=n;i>=1;i--)sa[c[X[i]]--]=i;
        for(int k=1,p=0;k<=n;k=k<<1,p=0)
        {
            for(int i=n-k+1;i<=n;i++)Y[++p]=i;
            for(int i=1;i<=n;i++)if(sa[i]>k)Y[++p]=sa[i]-k;
            for(int i=1;i<=m;i++)c[i]=0;
            for(int i=1;i<=n;i++)c[X[i]]++;
            for(int i=2;i<=m;i++)c[i]+=c[i-1];
            for(int i=n;i>=1;i--)sa[c[X[Y[i]]]--]=Y[i],Y[i]=0;
            swap(X,Y);p=1;X[sa[1]]=1;
            for(int i=2;i<=n;i++)
            {
                if(Y[sa[i]]==Y[sa[i-1]]&&Y[sa[i]+k]==Y[sa[i-1]+k])X[sa[i]]=p;
                else X[sa[i]]=++p;
            }
            if(p==n)return;m=p;
        }
    }
    void Height()
    {
        ll k=0;
        for(int i=1;i<=n;i++)rk[sa[i]]=i;
        for(int i=1;i<=n;i++)
        {
            if(rk[i]==1)continue;
            if(k)k--;
            int j=sa[rk[i]-1];
            while(i+k<=n&&j+k<=n&&ch[i+k]==ch[j+k])k++;
            height[rk[i]]=k;
        }
    }
    void St()
    {
        for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
        for(int i=1;i<=n;i++)st[i][0]=height[i];
        for(int j=1;j<=20;j++)for(int i=1;i+(1<<j)-1<=n;i++)
            st[i][j]=min(st[i][j-1],st[i+(1<<j-1)][j-1]);
    }
    int Lcp(int l,int r) //原数组中 l,r的lcp长度 
    {
        if((l=rk[l])>(r=rk[r]))swap(l,r); //若是直接在后缀数组sa[i]上求就删除 
        int d=lg[r-l++];
        return min(st[l][d],st[r-(1<<d)+1][d]); 
    }
}SA;
View Code

题目:

1.P3809 【模板】后缀排序

板子

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 const int N=1e6+3;
 6 int n,m=200,X[N],Y[N],c[N],sa[N],height[N],rk[N];
 7 char ch[N];
 8 void Sa()
 9 {
10     for(int i=1;i<=n;i++)X[i]=ch[i],c[X[i]]++;
11     for(int i=2;i<=m;i++)c[i]+=c[i-1];
12     for(int i=n;i>=1;i--)sa[c[X[i]]--]=i;
13     for(int k=1,p=0;k<=n;k=k<<1,p=0)
14     {
15         for(int i=n-k+1;i<=n;i++)Y[++p]=i;
16         for(int i=1;i<=n;i++)if(sa[i]>k)Y[++p]=sa[i]-k;
17         for(int i=1;i<=m;i++)c[i]=0;
18         for(int i=1;i<=n;i++)c[X[i]]++;
19         for(int i=2;i<=m;i++)c[i]+=c[i-1];
20         for(int i=n;i>=1;i--)sa[c[X[Y[i]]]--]=Y[i],Y[i]=0;
21         swap(X,Y);p=1;X[sa[1]]=1;
22         for(int i=2;i<=n;i++)
23         {
24             if(Y[sa[i]]==Y[sa[i-1]]&&Y[sa[i]+k]==Y[sa[i-1]+k])X[sa[i]]=p;
25             else X[sa[i]]=++p;
26         }
27         if(p==n)return;m=p;
28     }
29 }
30 void Height()
31 {
32     int k=0;
33     for(int i=1;i<=n;i++)rk[sa[i]]=i;
34     for(int i=1;i<=n;i++)
35     {
36         if(rk[i]==1)continue;
37         if(k)k--;
38         int j=sa[rk[i]-1];
39         while(i+k<=n&&j+k<=n&&ch[i+k]==ch[j+k])k++;
40         height[rk[i]]=k;
41     }
42 }
43 int main()
44 {
45     cin>>(ch+1);n=strlen(ch+1);
46     Sa();Height();
47     for(int i=1;i<=n;i++)cout<<sa[i]<<" ";
48     return 0; 
49 }
View Code

 

标签:ch,后缀,int,数组,--,SA,sa
From: https://www.cnblogs.com/Hanghang007/p/17599145.html

相关文章

  • sysaux或system表空间使用率高
    sysaux解决方案查看表空间使用率setlinesize200settaboffSELECTa.tablespace_name,TRUNC(tablespace_size*b.block_size/1024/1024)"Total_space(MB)",TRUNC(used_space*b.block_size/1024/1024)"Used_space(MB)",TRUN......
  • SpringDataJpa对拿到的对象进行set,但是不save,数据库也能自动更新,由于使用了注解 @Tran
    SpringDataJpa对拿到的对象进行set,但是不save,数据库也能自动更新,由于使用了注解@Transactional事务进行处理原文链接:https://blog.csdn.net/qq_19903753/article/details/103367252SpringDataJpa对拿到的对象进行set,但是不save,数据库也能自动更新概述今天在进行coderev......
  • js处理数组,删除指定元素
    //获取元素下标Array.prototype.indexOf=function(val){for(vari=0;i<this.length;i++){if(this[i]==val){returni;}}return-1;}//根据下标删除元素Ar......
  • 什么时候该用数组型容器、什么时候该用链表型容器?
    选择数组型容器还是链表型容器取决于特定的使用场景和需求。以下是一些指导原则:使用数组型容器的情况:快速随机访问:数组在具有固定大小的情况下,可以通过索引进行快速随机访问,时间复杂度为O(1)。这是因为数组的元素在内存中是连续存储的。内存连续性:数组在内存中是连续存储......
  • 淘宝天猫实时销量API接口(item_get_sales - 获取商品销量详情接口),30天销量API接口
    一、淘宝天猫实时销量API接口(item_get_sales-获取商品销量详情接口),实时销量接口主要是用于监控淘宝天猫的商品销量变化,可以获取到商品ID,商品链接,标题,价格,图片链接,库存数量,价格,30天销量,总销量等参数,页面上有的数据可以拿到,接口代码对接如下:1.公共参数名称类型必须描述keyString是......
  • 【Salesforce】【lwc】@api @track @wire
    一、@api@track@wire的区别1.@track注解private类型的reactive变量。2.@api注解public类型的reactive变量(public类型:即可暴露给其他的APP用来可以赋值注入)。3.@wire:我们常用的注解除了@track以及@api以外,还会经常使用@wire,区别为前两个是只针对前台的,wire既可以用在前台也......
  • 报错:WARNING: cannot load logging configuration file, logging is disabled
    问题:在webots里使用rospy时报warning。分析:无解决方案:参考https://blog.csdn.net/ckkboy/article/details/985048801.在/etc/下创建ros目录cd/etc/sudomkdirros2.将python_logging.conf文件复制到/etc/ros/下sudocp/opt/ros/melodic/etc/ros/python_log......
  • js如何实现对象数组的深度复制 记录记录
    背景:偶然发现的bug,列表页做多选的时候,做了一次数据格式的转换consttemp=me.multipleSelection;temp.forEach(p=>{p.trainTicketType=p.trainTicketType.split(',');requestList.push(p);})此时如果......
  • 枚举数组的所有子集
    参考: https://blog.csdn.net/weixin_43212830/article/details/122756392 https://blog.csdn.net/qq_34261446/article/details/103522369  /***@description:,枚举数组的所有子集*@author:luguilin*@date:2023-08-0116:22**/publicclassEnumAllSet......
  • 服务器磁盘IO是什么意思?SATA和固态硬盘的性能差异
    IO实际上是计算机用语,也写作I/O,指输入/输出(Input/Output)。硬盘IO就是指对字节的读取速度,即硬盘的读写能力。今天咱们主要讲一下服务器磁盘IO。服务器硬盘IO的性能也是服务器硬件配置中需要考虑的问题。SATA和固态硬盘的性能差异在哪里呢?首先,硬盘的数据存储在硬盘驱动器内各个扇区......