[破碎的状态] UOJ 35
一道后缀数组的模版题
Part 1:
后缀数组
做法:
我觉得一张图能很明确的表示..
这样就能开心的求出rank数组了
看图说话..
http://user.qzone.qq.com/664045109/blog/1388323241
http://user.qzone.qq.com/664045109/blog/1430923906
Part 2:
LCP
http://blog.csdn.net/shiqi_614/article/details/7982915
首先,我们要知道一个结论
我们设h[i]代表第i个子串与第b[rank[i]-1].id的最长公共前缀
那么h[i]>=h[i-1]-1
这么思考:
i和b[rank[i]-1].id都去掉它的第一位..(以下把后者简写为b[].id)
得到的东西的前面h[i-1]-1位和b[].id是一样的
而b[].id去掉第一位后得到的即是b[].id+1
那么lcp(i+1,b[].id+1)=h[i-1]-1
根据lcp的奇怪的性质
lcp(rank[i],rank[j]) = min(lcp(rank[i],rank[k]),lcp(rank[k],rank[j]))
我们可以发现它的答案至少是h[i-1]-1
代码:
Past:
#include<set> #include<map> #include<list> #include<queue> #include<stack> #include<string> #include<math.h> #include<time.h> #include<vector> #include<bitset> #include<memory> #include<utility> #include<fstream> #include<stdio.h> #include<sstream> #include<iostream> #include<stdlib.h> #include<string.h> #include<algorithm> using namespace std; char a[100005]; struct node { int x; int y; int id; friend bool operator < (const node &a,const node &b) { if (a.x==b.x) { return a.y<b.y; } return a.x<b.x; } }; node b[100005]; int rank[100005]; int n; void suffix_sort(int x) { int i; for (i=0;i<n;i++) { b[i].x=rank[b[i].id]; if (b[i].id+x<n) { b[i].y=rank[b[i].id+x]; } else { b[i].y=-1; } } sort(b,b+n); rank[b[0].id]=0; for (i=1;i<n;i++) { rank[b[i].id]=rank[b[i-1].id]; if (b[i-1]<b[i]) { rank[b[i].id]++; } } if (x>n) return; suffix_sort(x*2); } int c[100005]; int ans[100005]; int main() { #ifdef absi2011 freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif gets(a); n=strlen(a); int i; for (i=0;i<n;i++) { b[i].x=a[i]; b[i].id=i; } sort(b,b+n); rank[b[0].id]=0; for (i=1;i<n;i++) { rank[b[i].id]=rank[b[i-1].id]; if (b[i-1]<b[i]) { rank[b[i].id]++; } } suffix_sort(1); for (i=0;i<n;i++) { printf("%d ",b[i].id+1); } putchar(10); int now=0; for (i=0;i<n;i++) { if (rank[i]==n-1) { now=0; continue; } int t=b[rank[i]+1].id; now--; if (now<0) now=0; for (;;) { if (a[now+t]==a[now+i]) { now++; } else { break; } } ans[rank[i]]=now; } for (i=0;i<n-1;i++) { printf("%d ",ans[i]); } return 0; }
Now:
#include<set> #include<map> #include<list> #include<queue> #include<stack> #include<math.h> #include<string> #include<time.h> #include<bitset> #include<vector> #include<memory> #include<utility> #include<stdio.h> #include<sstream> #include<fstream> #include<iostream> #include<stdlib.h> #include<string.h> #include<algorithm> using namespace std; char a[100005]; struct node { int x; int y; int id; friend bool operator < (const node &a,const node &b) { if (a.x==b.x) return a.y<b.y; return a.x<b.x; } }; node b[100005]; int n; int c[100005]; int lcp[100005]; void preffix_sort(int x=1) { if (x>n) return; int i; for (i=0;i<n;i++) { if (b[i].id+x<n) { b[i].y=c[b[i].id+x]; } else { b[i].y=-1; } } sort(b,b+n); for (i=0;i<n;i++) { if ((i==0)||(b[i-1]<b[i])) { c[b[i].id]=i; } else { c[b[i].id]=c[b[i-1].id]; } } for (i=0;i<n;i++) { b[i].x=c[b[i].id]; } preffix_sort(x*2); } int ans[100005]; int main() { #ifdef absi2011 freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif scanf("%s",a); int i; for (i=0;a[i]!='\0';i++) { b[i].x=a[i]; b[i].y=0; b[i].id=i; } n=i; sort(b,b+n); for (i=0;i<n;i++) { c[b[i].id]=b[i].x; } preffix_sort(); for (i=0;i<n;i++) { printf("%d ",b[i].id+1); } printf("\n"); int now=0; for (i=0;i<n;i++) { if (c[i]==0) { now=0; continue; } now--; if (now<0) now=0; int t=b[c[i]-1].id; for (;;) { if (a[i+now]==a[t+now]) { now++; } else { break; } } ans[c[i]]=now; } for (i=1;i<n;i++) { printf("%d ",ans[i]); } return 0; }