Description
Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can‘t predict the quality of milk from one day to the next, there are some regular patterns in the daily milk quality.
To perform a rigorous study, he has invented a complex classification scheme by which each milk sample is recorded as an integer between 0 and 1,000,000 inclusive, and has recorded data from a single cow over N (1 ≤ N ≤ 20,000) days. He wishes to find the longest pattern of samples which repeats identically at least K (2 ≤ K ≤ N) times. This may include overlapping patterns -- 1 2 3 2 3 2 3 1 repeats 2 3 2 3 twice, for example.
Help Farmer John by finding the longest repeating subsequence in the sequence of samples. It is guaranteed that at least one subsequence is repeated at least K times.
Input
Output
Sample Input
8 2 1 2 3 2 3 2 3 1
Sample Output
4
Source
#include <iostream> #include <stdio.h> #include <string.h> #include <stack> #include <queue> #include <map> #include <set> #include <vector> #include <math.h> #include <bitset> #include <algorithm> #include <climits> using namespace std; #define LS 2*i #define RS 2*i+1 #define UP(i,x,y) for(i=x;i<=y;i++) #define DOWN(i,x,y) for(i=x;i>=y;i--) #define MEM(a,x) memset(a,x,sizeof(a)) #define W(a) while(a) #define gcd(a,b) __gcd(a,b) #define LL long long #define N 20005 #define MOD 1000000007 #define INF 0x3f3f3f3f #define EXP 1e-8 int wa[N],wb[N],wsf[N],wv[N],sa[N]; int rank[N],height[N],s[N],a[N]; char str1[N],str2[N]; //sa:字典序中排第i位的起始位置在str中第sa[i] //rank:就是str第i个位置的后缀是在字典序排第几 //height:字典序排i和i-1的后缀的最长公共前缀 int cmp(int *r,int a,int b,int k) { return r[a]==r[b]&&r[a+k]==r[b+k]; } void getsa(int *r,int *sa,int n,int m)//n要包含末尾添加的0 { int i,j,p,*x=wa,*y=wb,*t; for(i=0; i<m; i++) wsf[i]=0; for(i=0; i<n; i++) wsf[x[i]=r[i]]++; for(i=1; i<m; i++) wsf[i]+=wsf[i-1]; for(i=n-1; i>=0; i--) sa[--wsf[x[i]]]=i; p=1; j=1; for(; 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++) wsf[i]=0; for(i=0; i<n; i++) wsf[wv[i]]++; for(i=1; i<m; i++) wsf[i]+=wsf[i-1]; for(i=n-1; i>=0; i--) sa[--wsf[wv[i]]]=y[i]; t=x; x=y; y=t; x[sa[0]]=0; for(p=1,i=1; i<n; i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++; } } void getheight(int *r,int n)//n不保存最后的0 { int i,j,k=0; for(i=1; i<=n; i++) rank[sa[i]]=i; for(i=0; i<n; i++) { if(k) k--; else k=0; j=sa[rank[i]-1]; while(r[i+k]==r[j+k]) k++; height[rank[i]]=k; } } int ans,n,m; int fun(int k) { int i,maxn,minn=sa[1],cnt = 1; UP(i,2,n) { if(height[i]>=k)//首先最长公共前缀肯定要大于现在枚举的长度 { cnt++;//看连续的到底有几个 minn = min(minn,sa[i]);//这一组中,长度最小的子串是多长 } else { cnt = 1;//如果不行,那么重新分组 minn = sa[i]; } if(cnt>=m)//次数超过了,那么这个k长度下是可行的 return 1; } return 0; } int main() { int i,j,k,maxn; W((~scanf("%d%d",&n,&m))) { ans = maxn = 0; UP(i,0,n-1) { scanf("%d",&s[i]); maxn = max(maxn,s[i]); } s[n] = 0; getsa(s,sa,n+1,maxn+1); getheight(s,n); int l = 1,r = n; W(l<=r) { int mid = (l+r)/2; if(fun(mid)) { ans = mid; l=mid+1; } else r = mid-1; } printf("%d\n",ans); } return 0; }
原文地址:http://blog.csdn.net/libin56842/article/details/46236377