后缀数组 TYVJ P1860 后缀数组
/*P1860 后綴數組
時間: 1000ms / 空間: 131072KiB / Java類名: Main
描述
我們定義一個字符串的后綴suffix(i)表示從s[i]到s[length(s)]這段子串。
后綴數組(Suffix array)SA[i]中存放著一個排列,滿足suffix(sa[i])<suffix(sa[i+1]) 按照字典序方式比較
定義height[i]表示suffix(sa[i])與suffix(sa[i-1])之間的最長公共前綴長度,其中height[1]=0
你的任務就是求出SA和height這兩個數組。字符串長度<=200000
輸入格式
一行,為描述中的字符串(僅會出現小寫字母)
輸出格式
共兩行,每行n個數,第一行為sa[i],第二行為height[i],其中每行的數均用空格隔開
測試樣例1
輸入
aabaaaab
輸出
4 5 6 1 7 2 8 3
0 3 2 3 1 2 0 1*/
//本題算法就是題目名,而且還是后綴數組最簡單的應用。
//關于后綴數組我不想多說,推薦 算法合集之《后綴數組——處理字符串的有力工具》此h非我代碼中的h。
//有時真想有人給我講講,自學是非常非常痛苦的。
//但有2個點超時,不過不管了。
#include<cstdio>
#include<iostream>
#include<cstring>
#define N 200008
using namespace std;
int n,sa[2][N],rk[2][N],a[N],v[N],k,h[N];
char ch[N];
void geng(int sa[N],int rk[N],int SA[N],int RK[N])
{
for(int i=1;i<=n;i++)
v[rk[sa[i]]]=i;
for(int i=n;i;i--)
if(sa[i]>k)
SA[v[rk[sa[i]-k]]--]=sa[i]-k;
for(int i=n-k+1;i<=n;i++)
SA[v[rk[i]]--]=i;
for(int i=1;i<=n;i++)
RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i]]!=rk[SA[i-1]]||rk[SA[i]+k]!=rk[SA[i-1]+k]);
return;
}
int main()
{
gets(ch+1);
n=strlen(ch+1);
for(int i=1;i<=n;i++)
a[i]=ch[i]-'a'+1;
int p=0,q=1;
for(int i=1;i<=n;i++)
v[a[i]]++;
for(int i=2;i<27;i++)
v[i]+=v[i-1];
for(int i=1;i<=n;i++)
sa[p][v[a[i]]--]=i;
for(int i=1;i<=n;i++)
rk[p][sa[p][i]]=rk[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]);
for(k=1;k<n;k<<=1)
{
geng(sa[p],rk[p],sa[q],rk[q]);
swap(p,q);
}
for(int i=1;i<=n;i++)
printf("%d ",sa[p][i]);
printf("\n");
k=0;
for(int i=1;i<=n;i++)
if(rk[p][i]==1)
h[1]=0;
else
{
int j=sa[p][rk[p][i]-1];
for(;a[i+k]==a[j+k];k++);
h[rk[p][i]]=k;
if(k>0)
k--;
}
for(int i=1;i<=n;i++)
printf("%d ",h[i]);
return 0;
}
轉載于:https://www.cnblogs.com/xydddd/p/5150532.html
總結
以上是生活随笔為你收集整理的后缀数组 TYVJ P1860 后缀数组的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第6周 搜索与排序
- 下一篇: Apache多站点配置详解