首页 > 代码库 > 后缀数组
后缀数组
具体请看论文....
POJ 1743 Musical Theme
不重叠的最长重复子串
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;#define N 20100int p[N];int sa[N],rank[N],height[N];int wa[N],wb[N],c[N];//sa[i] 表示排名为i的下标//rank[i]表示i的排名//height[i]表示sa[i]和sa[i-1]的最长前缀void build_sa(int s[],int n,int m){ int i,j,p,*x = wa,*y = wb; //初始化基数排序 for(i = 0;i < m;i ++) c[i] = 0; for(i = 0;i < n;i ++) c[x[i] = s[i]] ++; for(i = 1;i < m;i ++) c[i] += c[i-1]; for(i = n-1;i >= 0;i --) sa[--c[x[i]]] = i; for(j = 1;j <= n;j <<= 1) { p = 0; //y[i] 表示第二关键字排名为i的下标 for(i = n-j;i < n;i ++) y[p++] = i; //如果后缀长度不到j的,第二关键字排名靠前 for(i = 0;i < n;i ++) if(sa[i] >= j) y[p++] = sa[i] - j; //sa[i] < j的时候不可能为第二关键字,位置sa[i]-j的第二关键字为sa[i], //他的排名为p //按第一关键字排序 for(i = 0;i < m;i ++) c[i] = 0; for(i = 0;i < n;i ++) c[x[y[i]]] ++; for(i = 1;i < m;i ++) c[i] += c[i-1]; //按y数组的存的下标顺序,基数排序 for(i = n-1;i >= 0;i --) sa[--c[x[y[i]]]] = y[i]; swap(x,y); //生成新的x数组,交换成y,是为了节省空间.... p = 1;x[sa[0]] = 0; //如果两个关键字都一样,下次的第一关键字一样。 for(i = 1;i < n;i ++) x[sa[i]] = y[sa[i-1]] == y[sa[i]]&&y[sa[i-1]+j] == y[sa[i]+j]?p-1:p++; if(p >= n) break; m = p; }}void get_height(int s[],int n){ int i,j,k = 0; for(i = 1;i <= n;i ++) rank[sa[i]] = i; //看论文,有证明 for(i = 0;i < n;i ++) { if(k) k--; j = sa[rank[i]-1]; while(s[i+k]==s[j+k]) k ++; height[rank[i]] = k; }}int judge(int mid,int n){ int minz,maxz,i; minz = maxz = sa[1]; for(i = 2;i <= n;i ++) { if(height[i] < mid) { minz = maxz = sa[i]; } else { maxz = max(maxz,sa[i]); minz = min(minz,sa[i]); if(maxz-minz > mid) return 1; } } return 0;}int main(){ int n,i; while(scanf("%d",&n)!=EOF) { if(n == 0) break; for(i = 0;i < n;i ++) scanf("%d",&p[i]); for(i = 0;i < n-1;i ++) p[i] = p[i+1] - p[i] + 90; n --; p[n] = 0; build_sa(p,n+1,200); get_height(p,n); int str,mid,end; str = 1; end = n/2; while(str < end) { mid = (str+end + 1)/2; if(judge(mid,n)) str = mid; else end = mid-1; } if(end >= 4) printf("%d\n",end+1); else printf("0\n"); } return 0;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。