POj 3581 看起来不像后缀数组的后缀数组
2016-08-04 21:44
417 查看
先离散化数据
离散化:当数据只与它们之间的相对大小有关,而与具体是多少无关时,可以进行离散化。
思路 1:输入时反转输入,因为题目要求
2:找到最小的 i 满足 sa[i] >1 把这个后缀输出
3:翻倍剩余的字符,翻倍是因为 如 2 0 1 0 1这样的串会因为长度的问题导致字典序排序失败
4:之后对翻倍的那一段数组进行一次后缀数组
5: 求出 第一个小于第一次的边界值并且不为0的下标,之后输出都到 边界位置
6:之后把剩余的前半部分输出
7: 具体看代码
离散化:当数据只与它们之间的相对大小有关,而与具体是多少无关时,可以进行离散化。
思路 1:输入时反转输入,因为题目要求
2:找到最小的 i 满足 sa[i] >1 把这个后缀输出
3:翻倍剩余的字符,翻倍是因为 如 2 0 1 0 1这样的串会因为长度的问题导致字典序排序失败
4:之后对翻倍的那一段数组进行一次后缀数组
5: 求出 第一个小于第一次的边界值并且不为0的下标,之后输出都到 边界位置
6:之后把剩余的前半部分输出
7: 具体看代码
#include <stdio.h> #include <algorithm> #include <string.h> #define maxs 200020 using namespace std; struct node { int id; int ns; }nd[maxs]; bool nodecmp(node a,node b) { if(a.ns!=b.ns) return a.ns<b.ns; return a.id<b.id; } int wa[maxs],wb[maxs],wv[maxs],ws[maxs]; int cmp(int *r,int a,int b,int l) { return r[a]==r[b]&&r[a+l]==r[b+l]; } void getsa(int *r,int *sa,int n,int m) { int i,j,p,*x=wa,*y=wb; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[x[i]=r[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p) { for(p=0,i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<n;i++) wv[i]=x[y[i]]; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[wv[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i]; for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)? p-1:p++; } } int s[maxs],sa[maxs]; int main() { int n,i,j; scanf("%d",&n); for(i=n-1;i>=0;i--) { scanf("%d",&nd[i].ns); nd[i].id=i; } sort(nd,nd+n,nodecmp); for(i=0;i<n;i++) { if(i&&nd[i].ns==nd[i-1].ns) s[nd[i].id]=s[nd[i-1].id]; else s[nd[i].id]=i+1; } s =0; getsa(s,sa,n+1,n+10); //printf("******************\n"); for(i=1;i<=n&&sa[i]<2;i++); int first=sa[i]; for(i=first;i<n;i++) printf("%d\n",nd[s[i]-1].ns); for(i=0;i<first;i++) s[i+first]=s[i]; first*=2; s[first]=0; getsa(s,sa,first+1,n+10); for(i=1;i<first&&(sa[i]==0||sa[i]>=first/2);i++); int second=sa[i]; for(i=second;i<first/2;i++) printf("%d\n",nd[s[i]-1].ns); for(i=0;i<second;i++) printf("%d\n",nd[s[i]-1].ns); return 0; }
相关文章推荐
- POJ 3581 启发:后缀数组求最小表示
- poj 3581 后缀数组 详解
- POJ 3581 Sequence [后缀数组]
- |Poj 3581|后缀数组|Sequence
- poj 1743 字符串 后缀数组 不可重叠最长重复子串
- POJ 2406 连续重复字符串(KMP)和后缀数组
- 【后缀数组求最长回文子串】POJ 3974
- 【后缀数组求重复次数最多的连续重复子串】SPOJ687 POJ3693
- 【倍增后缀数组】 poj1743 &2406& 3261 & 3294 & 2774
- POJ 1226 Substrings(后缀数组+二分)
- poj 3450/poj 3080 多串最长公共子串 后缀数组
- poj 2774 Long Long Message【后缀数组】
- poj 1743 Musical Theme 后缀数组
- poj 3261 Milk Patterns 最长的出现最少k次的重复(可重叠)子串 后缀数组
- poj 3261 Milk Patterns【后缀数组】
- POJ 1743 Musical Theme(后缀数组求不可重叠最长重复子串)
- poj 3450 Corporate Identity【后缀数组,求多个串的最长公共子串】
- POJ2774 Long Long Message——后缀数组——pku2774
- 【后缀数组求可重叠的k 次最长重复子串】POJ 3261
- poj 3261 Milk Patterns 【后缀数组】