首页 > 编程知识 正文

acwing算法基础,后缀树与后缀数组

时间:2023-05-06 20:46:25 阅读:173121 作者:4879

主题: https://www.AC wing.com/problem/content/2717 /

指定长度为n n n的字符串。 只包含大小写和数字。 将字符串中的nn个字符的位置编号依次设为1n1n1n。 用其开头字符在字符串中的位置编号表示该字符串的nn个非空后缀。 按词典顺序对这n n n个非空后缀进行排序,并给出两个数组S A SA SA和H e i g h t Height Height。 排序完成后,用S A [ i ] SA[i] SA[i]记录II的非空后缀的编号,用H e i g h t [ i ] Height[i] Height[i]记录III的非空后缀和I1I1I1的非空后缀的最长公共前缀请求这两个排列。

输入格式:

总共一行,包含只包含长度为NN的大小写或数字的字符串。

输出格式:

第一行包含表示SA数组的nn个整数。

第二行包含nn个表示Height数组的整数。

数据范围:

1n1061n10 ^ 61n106

后缀序列的结构通常用倍频法制作。

# include iostream # includecstringusingnamespacestd; const int N=1e6 10; int n,m; char s[N]; //sa[i]位是第几个后缀//rk[i]第几个后缀//height[i]是sa[i]和sa[i - 1]的最长公共前缀长度int sa[N],x[N],y[N] i=n; I ) c(x ) I )=s ) I ); for(intI=2; i=m; I ) c(I )=c(I-1 ); for(intI=n; I; I----sa[c[x[I]]----]=I; for(intk=1; k=n; k=1) { int num=0; for(intI=n-k1; i=n; I ) y[ num]=i; for(intI=1; i=n; I ) if(sa[I]k ) y[ num]=sa[i] - k; for(intI=1; i=m; I ) c[i]=0; for(intI=1; i=n; I ) c(x ) I ); for(intI=2; i=m; I ) c(I )=c(I-1 ); for(intI=n; I; I---sa [ c [ x [ y [ I ] ]-- ]=y [ I ],y[i]=0; swap(x,y ); x[sa[1]]=1,num=1; for(intI=2; i=n; I ) x[sa[I] () y[sa[I] )=y[sa[I-1] ) y[sa[I]k]==y[sa[I-1]k]? num : num; if(num==n ) break; m=num; }}void get_height () ) for ) intI=1; i=n; I ) rk[sa[i]]=i; for(intI=1,k=0; i=n; I ) if(rk[I]==1) continue; if(k ) k----; int j=sa[rk[i] - 1]; wile(Ik=njk=ns[Ik]==s[jk] ) k; height[rk[i]]=k; }}int main () Scanf ) ' %s ',s 1 ); n=Strlen(s1 ),m=122; get_sa (; get_height (; for(intI=1; i=n; I ) printf('%d ',sa[i]; puts (' ); for(intI=1; i=n; I ) printf('%d ',height[i]; puts (' ); 返回0; }时间复杂度o(O(nlogn ) o ) n(logn ) o ) nlogn ),空间o ) n ) o ) n ) n ) n ) )。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。