poj1743:http://poj.org/problem?id=1743
题意:题意抽象出来就是给你一个序列,然后找一个长度不少于5的没有重复的等差数列。
题解:每相邻的两个数做差,然后转化成求字符串没有重复的出现两次以上的最大长度。具体就是,先求后缀数组和H数组,二分长度,然后分组,在每个组里面找sa的最大值和最小值,当最大值-最小值大于k的时候,就是满足的。但是这里poj的数据实在是太弱了,n==9的时候哦也可以过,有点失望了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int maxn=20010; 6 char str[maxn]; 7 int wa[maxn],wb[maxn],wv[maxn],wn[maxn],a[maxn],sa[maxn]; 8 int f[maxn]; 9 int cmp(int* r,int a,int b,int l) 10 { 11 return r[a]==r[b]&&r[a+l]==r[b+l]; 12 } 13 //n为字符串长度,m为字符的取值范围,r为字符串。后面的j为每次排序时子串的长度 14 void DA(int* r,int* sa,int n,int m) 15 { 16 int i,j,p,*x=wa,*y=wb,*t; 17 ///对R中长度为1的子串进行基数排序 18 for(i=0; i<m; i++)wn[i]=0; 19 for(i=0; i<n; i++)wn[x[i]=r[i]]++; 20 for(i=1; i<m; i++)wn[i]+=wn[i-1]; 21 for(i=n-1; i>=0; i--)sa[--wn[x[i]]]=i; 22 for(j=1,p=1; p<n; j*=2,m=p) 23 { 24 //利用了上一次基数排序的结果,对待排序的子串的第二关键字进行了一次高效地基数排序 25 for(p=0,i=n-j; i<n; i++)y[p++]=i; 26 for(i=0; i<n; i++)if(sa[i]>=j)y[p++]=sa[i]-j; 27 ///基数排序 28 for(i=0; i<n; i++)wv[i]=x[y[i]]; 29 for(i=0; i<m; i++)wn[i]=0; 30 for(i=0; i<n; i++)wn[wv[i]]++; 31 for(i=1; i<m; i++)wn[i]+=wn[i-1]; 32 for(i=n-1; i>=0; i--)sa[--wn[wv[i]]]=y[i]; 33 ///当p=n的时候,说明所有串都已经排好序了 34 ///在第一次排序以后,rank数组中的最大值小于p,所以让m=p 35 for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++) 36 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 37 } 38 return; 39 } 40 ///后缀数组 计算height数组 41 /** 42 height数组的值应该是从height[1]开始的,而且height[1]应该是等于0的。 43 原因是,+因为我们在字符串后面添加了一个0号字符,所以它必然是最小的 44 一个后缀。而字符串中的其他字符都应该是大于0的(前面有提到,使用倍 45 增算法前需要确保这点),所以排名第二的字符串和0号字符的公共前缀 46 (即height[1])应当为0.在调用calheight函数时,要注意height数组的范 47 围应该是[1..n]。所以调用时应该是calheight(r,sa,n) 48 而不是calheight(r,sa,n+1)。*/ 49 int rank[maxn],height[maxn]; 50 void calheight(int* r,int* sa,int n) 51 { 52 int i,j,k=0; 53 for(i=1; i<=n; i++)rank[sa[i]]=i; 54 for(i=0; i<n; height[rank[i++]]=k) 55 for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++); 56 return; 57 } 58 int t; 59 bool judge(int mid){ 60 int minn=sa[1],maxn=sa[1]; 61 for(int i=1;i<=t;i++){ 62 if(height[i]<mid){ 63 minn=sa[i],maxn=sa[i]; 64 } 65 else{ 66 minn=min(minn,sa[i]); 67 maxn=max(maxn,sa[i]); 68 if(maxn-minn>mid)return true; 69 } 70 } 71 return false; 72 } 73 74 int main(){ 75 while(~scanf("%d",&t)&&t){ 76 f[0]=0; 77 for(int i=1;i<=t;i++) 78 scanf("%d",&f[i]); 79 for(int i=1;i<=t;i++){ 80 a[i-1]=f[i]-f[i-1]+100; 81 } 82 a[t]=0; 83 DA(a,sa,t+1,190); 84 calheight(a,sa,t); 85 int l=0,r=t,ans=0; 86 while(l<=r){ 87 // printf("%d %d ",l,r); 88 int mid=(l+r)/2; 89 if(judge(mid)){ 90 ans=mid; 91 l=mid+1; 92 } 93 else 94 r=mid-1; 95 } 96 if(ans>=4) 97 printf("%d ",ans+1); 98 else 99 printf("0 "); 100 } 101 return 0; 102 }