spoj687(后缀数组)
http://www.spoj.com/problems/REPEATS/
题意:给一串字符,需要你求这一串字符中有连续重复的字符的重复次数.......
思路:这是和poj3693一种类型的题目......这里是详细解答:http://www.cnblogs.com/ziyi--caolu/p/3193823.html
注意:还需注意的地方,我一直图方便,再求lcp值时,总是从height值的起点到终点,其实应该是起点+1
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; #define min(x,y) x>y? y:x #define maxn 51000 int wa[maxn],wv[maxn],sa[maxn],rank[maxn],height[maxn],wb[maxn],wsf[maxn]; int s[maxn],dp[maxn][40]; 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) { 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) { 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; } } void rmq_init(int n) { for(int i=1;i<=n;i++) dp[i][0]=height[i]; for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;i++) dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } int rmq(int l,int r) { int ll=rank[l]; int rr=rank[r]; if(ll>rr) { int tmp=ll; ll=rr; rr=tmp; } ll++; //注意,ll要++ int k=0; while((1<<(k+1))<=rr-ll+1) k++; return min(dp[ll][k],dp[rr-(1<<k)+1][k]); } int main() { int text; scanf("%d",&text); while(text--) { int n; scanf("%d",&n); for(int i=0;i<n;i++) { char ch[10]; scanf("%s",&ch); s[i]=ch[0]-'a'+1; } s[n]=0; getsa(s,sa,n+1,3); getheight(s,n); rmq_init(n); int ans=0; for(int i=1;i<=n/2;i++) { for(int j=0;j<n-i;j+=i) { if(s[j]!=s[i+j]) continue; int k=rmq(j,i+j); int d=k/i+1; int r=i-k%i; int cnt=0; for(int m=j-1;m>j-i&&m>=0&&s[m]==s[m+i];m--) { cnt++; if(cnt==r) { d++; } } if(ans<d) ans=d; } } printf("%d\n",ans); } return 0; }
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。