[UOJ#35] [UOJ后缀数组模板题] 后缀排序 [后缀数组模板]

后缀数组,解决字符串问题的有利工具,本题代码为倍增SA算法

具体解释详见2009年国家集训队论文

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cmath>
 7 #include <ctime>
 8
 9 using namespace std;
10
11 int    str[110000];
12 int    Barrel[2][110000],U[110000],Tmp[110000],SA[110000],H[110000];
13 char    r[110000];
14
15 void    Calc_H(const int & n,const int * Rank)
16 {
17     int    i,j,k=0;
18     for(i=0;i<n;H[Rank[i++]]=k)
19         for(k?k--:0,j=SA[Rank[i]-1];str[i+k]==str[j+k];++k);
20     return ;
21 }
22
23 bool    cmp(const int * s,const int a,const int b,const int l)
24 {
25     return s[a]==s[b] && s[a+l]==s[b+l];
26 }
27
28 int*    Get_SA(const int & n,int  m)
29 {
30     int    i,j,p,*x=Barrel[0],*y=Barrel[1];
31     memset(U,0,sizeof(U));
32     for(i=0;i<n;++i)U[x[i]=str[i]]++;
33     for(i=1;i<m;++i)U[i]+=U[i-1];
34     for(i=n-1;i>=0;--i)SA[--U[x[i]]]=i;
35
36     for(j=1,p=1;p<n;j<<=1,m=p)
37     {
38         for(p=0,i=n-j;i<n;++i)y[p++]=i;
39         for(i=0;i<n;++i)if(SA[i]>=j)y[p++]=SA[i]-j;
40         for(i=0;i<n;++i)Tmp[i]=x[y[i]];
41         for(i=0;i<m;++i)U[i]=0;
42         for(i=0;i<n;++i)U[Tmp[i]]++;
43         for(i=1;i<m;++i)U[i]+=U[i-1];
44         for(i=n-1;i>=0;--i)SA[--U[Tmp[i]]]=y[i];
45         for(swap(x,y),p=1,x[SA[0]]=0,i=1;i<n;++i)
46         x[SA[i]]=cmp(y,SA[i-1],SA[i],j)?p-1:p++;
47     }
48     Calc_H(n,x);
49     return x;
50 }
51
52 int main()
53 {
54     int    i,n;
55     scanf("%s",r);
56     n=strlen(r);
57     for(i=0;i<n;++i)str[i]=r[i];
58
59     Get_SA(n+1,256);
60
61     for(i=1;i<=n;++i)printf("%d ",SA[i]+1);
62     printf("\n");
63     for(i=2;i<=n;++i)printf("%d ",H[i]);
64
65     return 0;
66 }

在计算H数组的时候因为在计算SA数组的程序中x所代表的数组中就是Rank数组,所以不需要重新计算

时间: 2024-08-12 23:51:50

[UOJ#35] [UOJ后缀数组模板题] 后缀排序 [后缀数组模板]的相关文章

poj3461 Oulipo (KMP模板题~) 前面哪些也是模板题 O.O

# include <stdio.h> # include <algorithm> # include <string.h> using namespace std; char a1[1000010],a2[1000010]; int next[1000010]; int len1,len2,cot; void Getnext() { int i=0,j=-1; next[0]=-1; while(i<=len1) { if(j==-1||a1[i]==a1[j]

【POJ 2104】 K-th Number 主席树模板题

达神主席树讲解传送门:http://blog.csdn.net/dad3zz/article/details/50638026 2016-02-23:真的是模板题诶,主席树模板水过.今天新校网不好,没有评测,但我立下flag这个代码一定能A.我的同学在自习课上考语文,然而机房党都跑到机房来避难了\(^o^)/~ #include<cstdio> #include<cstring> #include<algorithm> #define for1(i,a,n) for(i

js入门6数组的倒转与排序

1.得到文本框中录入的文本: 2.将文本拆分为字符数组: 3.调用Array对象的revert方法实现数组的倒转: 4.调用Array对象的sort方法实现数组的排序(按照文本): 5.调用Array对象的sort方法,并传入自定义的比较函数,对数组实现按数值排序. //数组操作function operateArray(t){    alert('1');    //拆分为数组    var array = document.getElementById("txtNumbers").

C实现数组中元素的排序

使用C实现数组中元素的排序,使得数组中的元素从小到大排列.只不过在这个过程中出了一点小问题,在C中进行数字交换的时候,必须要使用指针的,不能使用引用.在后面的文章中,我要学习一个在C中的引用和指针的区别.下面看一下我的代码吧. #include <stdio.h> void swap(int *a,int *b); void rest(int lels[],int count); /** * 该实例用于实现对用户输入的数组进行排序 * 要求的数组中的元素从小到大来咧 * * @brief ma

返回数组中的最大值和删除数组重复值-排序

//数组中最大值function getMax(arr){ //取该数组第一个值为最大值 var max=arr[0]; for(var i=0;i<arr.length;i++){ if(arr[i]>max){ max=arr[i] } } return max;} console.log(getMax([2,98,10,88])) /*--------------------------------------------------------------------*///删除数组重

uoj #35. 后缀排序

这是一道模板题. 读入一个长度为 n n 的由小写英文字母组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置.位置编号为 1 1 到 n n. 除此之外为了进一步证明你确实有给后缀排序的超能力,请另外输出 n?1 n?1 个整数分别表示排序后相邻后缀的最长公共前缀的长度. 输入格式 一行一个长度为 n n 的仅包含小写英文字母的字符串. 输出格式 第一行 n n 个整数,第 i i 个整数表示排名为 i i 的后缀的第一个字符在原串中的位

PKU 2774 Long Long Message (后缀数组练习模板题)

题意:给你两个字符串,求最长公共字串的长度. by:罗穗骞模板 #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define M 303 #define inf 0x3fffffff #define maxn 500000 #define ws ww #define rank RANK #define F

后缀数组 - 求最长回文子串 + 模板题 --- ural 1297

1297. Palindrome Time Limit: 1.0 secondMemory Limit: 16 MB The “U.S. Robots” HQ has just received a rather alarming anonymous letter. It states that the agent from the competing «Robots Unlimited» has infiltrated into “U.S. Robotics”. «U.S. Robots» s

poj 2774 Long Long Message(后缀数组入门题)

1 /****************************************************************** 2 题目: Long Long Message(poj 2774) 3 链接: http://poj.org/problem?id=2774 4 题意: 给两个字符串,找最长的公共子串 5 算法: 后缀数组 6 算法思想: 后缀数组就是套模板求先应得数组,这题用到了两个数组,分 7 别是sa[],height[];sa[i]表示所有后缀按字典数排序后以s[i