SA模板

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int M=100010;
 6 char S[M];
 7 int n,i,s[M],sa[M],wa[M],wb[M],wc[M],wd[M],height[M],rank[M];
 8 bool cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
 9 void getsa(int *r,int *sa,int n,int m){
10     int *x=wa,*y=wb,j,p;
11     for (i=0;i<n;i++)wc[x[i]=r[i]]++;
12     for (i=1;i<m;i++)wc[i]+=wc[i-1];
13     for (i=n-1;i>=0;i--)sa[--wc[x[i]]]=i;
14     for (j=1,p=1;p<n;j*=2,m=p){
15         p=0;
16         for (i=n-j;i<n;i++)y[p++]=i;
17         for (i=0;i<n;i++)if (sa[i]>=j)y[p++]=sa[i]-j;
18         for (i=0;i<n;i++)wd[i]=x[y[i]];
19         for (i=0;i<m;i++)wc[i]=0;
20         for (i=0;i<n;i++)wc[wd[i]]++;
21         for (i=1;i<m;i++)wc[i]+=wc[i-1];
22         for (i=n-1;i>=0;i--)sa[--wc[wd[i]]]=y[i];
23         swap(x,y);p=1;x[sa[0]]=0;
24         for (i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
25     }
26 }
27 void getheight(int *r,int *sa,int n){
28     int i,j,k=0;
29     for (i=1;i<=n;i++)rank[sa[i]]=i;
30     for (i=0;i<n;height[rank[i++]]=k){
31         if(k)k--;
32         j=sa[rank[i]-1];
33         while(r[i+k]==r[j+k])k++;
34     }
35 }
36 int main(){
37     scanf("%s",S);
38     n=strlen(S);
39     for (i=0;i<n;i++)s[i]=S[i]-‘a‘+1;
40     s[n]=0;
41     getsa(s,sa,n+1,100);
42     getheight(s,sa,n);
43     for (i=1;i<=n;i++)printf("%d ",sa[i]+1);puts("");
44     for (i=2;i<=n;i++)printf("%d ",height[i]);puts("");
45 }
时间: 2024-08-24 08:37:11

SA模板的相关文章

GDOI2015 解题报告

首先嘛现在发现题目这么水我还啥都没想出来正是呵呵了.接下来就口胡下GDOI的题解吧 PS:代码什么的要请联系我 题目:快戳我 Day1: T1:这个嘛,可以先找到起点所能到达的每个点然后判断该点能否到达终点,后一步可以发现如果从终点沿反向边遍历所能得到的所有点就是能到达终点的点,然后扫一下即可 在实现方面建议先把图建出来不要直接按照题意做 T2: 方法一:可以发现当做到第i个人的时候前i-2都已经覆盖,从i+2开始都未被覆盖,也就是说做到第i个人有关状态只有2^5种,然后就可以直接状态压缩dp了

POJ 1743 (后缀数组+不重叠最长重复子串)

题目链接: http://poj.org/problem?id=1743 题目大意:楼教主の男人八题orz.一篇钢琴谱,每个旋律的值都在1~88以内.琴谱的某段会变调,也就是说某段的数可以加减一个旋律范围的值.问这个谱子内最长不重叠的重复部分大小. 解题思路: 网上题解已经泛滥的题.很多细节都被先辈大神总结了. 在当年后缀数组还不是热门的时候,这题确实是神题. 首先对于旋律变调的处理: 比如123,123,ans=3. 变调之后:456,123,ans=0?不ans=3. 所以不能使用旋律的初始

[BZOJ4892][TJOI2017]DNA(后缀数组)

题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个碱基,依然能够表现出吃藕的性状.现在研究人员想知道这个基因在DNA链S0上的位置.所以你需要统计在一个表现出吃藕性状的人的DNA序列S0上,有多少个连续子串可能是该基因,即有多少个S0的连续子串修改小于等于三个字母能够变成S. 输入输出格式 输入格式: 第一行有一个数T,表示有几组数据 每组数据第一行一个长度不超过10^5的碱基

后缀数组备忘

SA写了就忘,SAM根本学不会,没救. SA模板: int n,sa[N],sa2[N],rk[N<<1],tmp[N<<1],h[N],cnt[N],f[N][20],lg2[N];//sa[i] 在原串中排名第i的长度为k子串以sa[i]为开头(相同串在前面的排名靠前) rk[i] 在原串中以i为开头的长度为k子串排名第rk[i](相同串排名相同)//sa2[i] 辅助基数排序,在k+1~n+k中排名第i的长度为k子串以sa2[i]+k开头 tmp[i] 临时存储rk[i] c

后缀数组(Suffix Array)模板及简析——Part 1:构建SA和rank数组

后缀数组(Suffix Array,SA)是处理字符串的有力工具.它比后缀树更易实现,占用空间更少,并且同样可以解决千变万化的字符串问题 首先推荐罗穗骞的论文(网上搜一下就能搜到),里面对后缀数组的定义.实现和应用都做了详细的阐述 然而不幸的是罗神犇的代码简直魔性,蒟蒻表示这代码压的根本看不懂啊…… 所以在理解了后缀数组的构建过程之后,我重新写了一份模板代码.虽然啰嗦了点(代码比较大,而且变量名故意拉长了),不过相对比较好懂 而且论文中用到的辅助空间是4N,我的模板用了3N,事实上还可以优化到只

ac自动机基础模板(hdu2222)

In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. Wiskey also wants to bring this feature to his image retrieval system. Every image have a long description, when users type some keywords to find the image, th

个中模板

学习jjh同学搞个模板集合 后缀数组: 1 int n,m; char s[310000]; 2 int rank[310000]; 3 int cnt[310000],cnt_rank[310000]; 4 int rank1[310000],rank2[310000]; 5 int SA[310000],tempSA[310000];//应该是桶 6 void get_suffix_rank(){ 7 memset(cnt,0,sizeof(cnt)); 8 //以下是对单个字母排序 9 f

后缀数组模板及解释

以前做过后缀数组,直接用模板,最近打算重新认真的学一遍.感觉学一个东西一定要弄懂了,不然到最后还是要重学. int wa[MAXN],wb[MAXN],wv[MAXN],Ws[MAXN]; void da(int *r,int *sa,int n,int m){//n表示字符串长度 + 1,包括添加的那个0,m表示取值的范围 //把单个字符进行基数排序 int *x = wa,*y = wb; for(int i = 0; i < m; i++)Ws[i] = 0; for(int i = 0;

hdu 4289 Control(网络流 最大流+拆点)(模板)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4289 Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1545    Accepted Submission(s): 677 Problem Description You, the head of Department o