题意:求一列数字中走向相同的两个字序列,长度要求大于5
题解:相邻数字求差,原题就变成求相同的长度大于4的子串。
[存疑:在保证两个子串不相交时觉得限定条件应该是大于x,但是wa了= = 不是很理解]
/************************************** Problem: 1743 User: G_lory Memory: 1392K Time: 204MS Language: G++ Result: Accepted **************************************/ //后缀数组 #include <stdio.h> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = int(2e5)+10; int cmp(int *r,int a,int b,int l){ return (r[a]==r[b]) && (r[a+l]==r[b+l]); } // 用于比较第一关键字与第二关键字, // 比较特殊的地方是,预处理的时候,r[n]=0(小于前面出现过的字符) int wa[N],wb[N],wss[N],wv[N]; int sa[N]; // 排第几的是谁 0~n-1 int rk[N], // 谁排第几 height[N]; // 排名相邻的两个后缀的最长公共前缀长度:suffix(sa[i-1])和(sa[i]) 的最长公共前缀, int a[N]; void DA(int *r,int *sa,int n,int m){ // 此处N比输入的N要多1,为人工添加的一个字符,用于避免CMP时越界 int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) wss[i]=0; for(i=0;i<n;i++) wss[x[i]=r[i]]++; for(i=1;i<m;i++) wss[i]+=wss[i-1]; for(i=n-1;i>=0;i--) sa[--wss[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++) wss[i]=0; for(i=0;i<n;i++) wss[wv[i]]++; for(i=1;i<m;i++) wss[i]+=wss[i-1]; for(i=n-1;i>=0;i--) sa[--wss[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } } void calheight(int *r,int *sa,int n){ // 此处N为实际长度 int i,j,k=0; for(i=1;i<=n;i++) rk[sa[i]]=i; for(i=0;i<n; height[rk[i++]] = k ) for(k?k--:0,j=sa[rk[i]-1]; r[i+k]==r[j+k]; k++); } bool ok(int x, int n) { int minn, maxn; minn = maxn = sa[1]; for (int i = 2; i <= n; ++i) { if (height[i] >= x) { minn = min(minn, sa[i]); maxn = max(maxn, sa[i]); } else { minn = maxn = sa[i]; } if (maxn - minn >= x) return true; } return false; } int main(int argc, char const *argv[]) { //freopen("in", "r", stdin); int n; while (cin >> n && n) { for (int i = 0; i < n; ++i) scanf("%d", a+i); for (int i = 0; i < n-1; ++i) a[i] = a[i+1] - a[i] + 100; a[--n] = 0; DA(a, sa, n+1, 200); calheight(a, sa, n); int l = 1, r = n; while (l + 1 < r) { int mid = (l+r) >> 1; if (ok(mid, n)) l = mid; else r = mid; } ++l; printf("%d\n", l < 5 ? 0 : l); } return 0; }
时间: 2024-10-08 10:04:52