xmu 1337 后缀数组 + 暴力匹配
http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1337
题意:在一个串中求出一个长度为n的、重复了m次的子串(不能重叠)。
思路:一直以为正解是后缀数组加其它高效的搜索方法。一水才知道,就是纯后缀数组+暴力匹配。
先用后缀数组求出 sa,height两个数组的值,当height[i]=n时,取出当前子串,进行暴力匹配。囧~~~

#include<stdio.h> #include<string.h> #include<stdlib.h> const int maxn = 101000; int wn[maxn],wa[maxn],wb[maxn],wv[maxn],a[maxn],sa[maxn],rank[maxn],height[maxn]; char r[maxn]; int Max(int x,int y){return x>y?x:y;} int Min(int x,int y){return x>y?y:x;} int cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; } void da(int *r,int *sa,int n,int m) { int i,j,p,*x=wa,*y=wb,*t; for(i = 0; i < m; ++ i) wn[i] = 0; for(i = 0; i < n; ++ i) wn[x[i]=r[i]]++; for(i = 1; i < m; ++ i) wn[i] += wn[i-1]; for(i = n - 1; i >= 0; --i) sa[--wn[x[i]]] = i; for(p = 1,j = 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 < m; ++ i) wn[i] = 0; for(i = 0; i < n; ++ i) wn[wv[i]=x[y[i]]]++; for(i = 1; i < m; ++ i) wn[i] += wn[i-1]; for(i = n - 1; i >= 0; --i) sa[--wn[wv[i]]] = y[i]; for(t = x,x = y,y = t,x[sa[0]] = 0,p=1,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) { int i,j,k = 0; for(i = 1; i <= n; ++ i){ rank[sa[i]] = i; height[i] = 0;} for(i = 0; i < n; height[rank[i++]]=k) for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k];++k); } int main() { int i,j,k,n,m,cnt; char as[2005],*p; while(scanf("%d %d",&n,&m)==2) { scanf("%s",r); for(i = 0; r[i]; ++ i) a[i] = static_cast<int>(r[i]); a[i] = 0; da(a,sa,i+1,256); calheight(a,sa,i); for(j = 1; j <= i; ++ j)if(height[j]==n) { for(k = 0; k < n; ++ k) as[k] = r[sa[j]+k]; as[k] = 0; p = r; p = strstr(p,as); p += n; cnt = 1; while(cnt<m){ p = strstr(p,as); if(p==NULL)break; cnt++; p += n; } if(cnt>=m)break; } puts(as); }return 0; }