首页 > 代码库 > 初涉后缀数组
初涉后缀数组
以POJ 1743为例。模板中的基数排序基于前向星。
具体证明过程详见 算法合集之《后缀数组——处理字符串的有力工具》,很不错的一篇论文。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <stack> #include <map> #include <ctime> #include <iomanip> #pragma comment(linker, "/STACK:1024000000"); #define EPS (1e-6) #define LL long long #define ULL unsigned long long #define _LL __int64 #define INF 0x3f3f3f3f #define Mod 1000000007 using namespace std; const int MAXN = 20510; int s[MAXN]; int Rank[2*MAXN],sa[2*MAXN],tr[2*MAXN],high[MAXN]; struct N { int v,next; }edge[2*MAXN]; int tail[MAXN],Top; inline void Link(int u,int v) { edge[Top].v = v; edge[Top].next = -1; edge[tail[u]].next = Top; tail[u] = Top++; } void Get_SA(int *s,int n) { memset(Rank,0,sizeof(Rank)); memset(sa,0,sizeof(sa)); int i,j,k,ans,site; for(i = max(n,200);i >= 0; --i) tail[i] = i,edge[i].next = -1; Top = max(n,200)+1; for(i = 1; i <= n; ++i) Link(s[i],i); ans = 1,site = 1; for(i = 0; i <= 200; ++i) { for(j = edge[i].next; j != -1; j = edge[j].next) sa[site++] = edge[j].v,Rank[edge[j].v] = ans; if(edge[i].next != -1) ans++; tail[i] = i,edge[i].next = -1; } for(k = 1;k <= n; k <<= 1) { Top = n+1; for(i = 1;i <= n; ++i) Link(Rank[sa[i]+k],sa[i]); site = 1; for(i = 0;i <= n; ++i) { for(j = edge[i].next;j != -1; j = edge[j].next) sa[site++] = edge[j].v; tail[i] = i,edge[i].next = -1; } Top = n+1; for(i = 1;i <= n; ++i) Link(Rank[sa[i]],sa[i]); site = 1; for(i = 1;i <= n; ++i) { for(j = edge[i].next;j != -1; j = edge[j].next) sa[site++] = edge[j].v; tail[i] = i,edge[i].next = -1; } for(tr[sa[1]] = 1,i = 2,ans = 1;i <= n; ++i) { if(Rank[sa[i]] != Rank[sa[i-1]] || Rank[sa[i]+k] != Rank[sa[i-1]+k]) ans++; tr[sa[i]] = ans; } for(i = 1;i <= n; ++i) Rank[i] = tr[i]; if(ans >= n) break; } for(i = 1,k = 1;i <= n; ++i) { if(k) k--; if(Rank[i] == 1) {k = 0;high[1] = n-sa[1]+1;continue;} j = sa[Rank[i]-1]; while(i+k <= n && j+k <= n && s[i+k] == s[j+k]) k++; high[Rank[i]] = k; } // // for(i = 1;i <= n; ++i) // printf("i = %2d SA = %2d Rank = %2d high = %2d\n",i,sa[i],Rank[i],high[i]); //以上为Rank,SA,HIGH的构造过程 } bool Check(int mid,int n) { int L = sa[1],R = sa[1],i; for(i = 2;i <= n; ++i) { if(high[i] >= mid) { L = min(sa[i],L),R = max(sa[i],R); if(L+mid < R) return true; } else L = sa[i],R = sa[i]; } return false; } int main() { int i,n; while(scanf("%d",&n) && n) { for(i = 1;i <= n; ++i) scanf("%d",&s[i]); for(i = n;i >= 2; --i) s[i] -= s[i-1]-100; Get_SA(s,n); int mid,anw = 0,Low = 1,High = n; while(Low <= High) { mid = (Low + High)>>1; if(Check(mid,n)) anw = max(anw,mid),Low = mid+1; else High = mid-1; } printf("%d\n",anw+1 < 5 ? 0 : anw+1); } return 0; }
初涉后缀数组
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。