POJ 3693 Maximum repetition substring(RMQ+后缀数组)

来源:互联网 发布:深圳知复科技有限公司 编辑:程序博客网 时间:2024/04/30 20:52


http://blog.csdn.net/acm_cxlove/article/details/7941205

lcp(i,j);

字符串suffix(i) 和 suffix(j)的最长公共前缀

然后就是比较神奇的简化。。


#include <stdio.h>  #include <math.h>  #include <string.h>  #include <algorithm>  #include<iostream>using namespace std;  const int N = 100010;    int r[N], tx[N], ty[N], rs[N], ranks[N], sa[N], height[N], rmq[N][20]; //rs基数排序  char s[N];    bool cmp(int *r, int a, int b, int len)  {      return (r[a] == r[b]) && (r[a + len] == r[b + len]);  }    void suffix(int n, int m) //n为长度,最大值小于m  {      int i, j, p, *x = tx, *y = ty, *t;      for(i = 0; i < m; ++i)          rs[i] = 0;      for(i = 0; i < n; ++i) {          x[i] = r[i];          ++rs[x[i]];      }      for(i = 1; i < m; ++i)          rs[i] += rs[i - 1];      for(i = n - 1; i >= 0; --i)          sa[--rs[x[i]]] = i;      for(j = p = 1; p < n; j <<= 1, 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)              rs[i] = 0;          for(i = 0; i < n; ++i)              ++rs[x[y[i]]];          for(i = 1; i < m; ++i)              rs[i] += rs[i - 1];          for(i = n - 1; i >= 0; --i)              sa[--rs[x[y[i]]]] = y[i];          t = x, x = y, y = t;          for(i = 1, p = 1, x[sa[0]] = 0; i < n; ++i) {              if(cmp(y, sa[i - 1], sa[i], j))                  x[sa[i]] = p - 1;              else                  x[sa[i]] = p++;          }      }      /**for(i = 0; i < n; ++i)         printf("%s\n", s + sa[i]);*/  }    void calheight(int n)  {      int i, j, k = 0;      for(i = 1; i <= n; ++i)          ranks[sa[i]] = i;      for(i = 0; i < n; ++i) {          if(k)              --k;          j = sa[ranks[i] - 1];          while(r[i + k] == r[j + k])              ++k;          height[ranks[i]] = k;      }  }    void initrmq(int n)  {      int i, k;      for(i = 2; i <= n; ++i)          rmq[i][0] = height[i];      for(k = 1; (1 << k) <= n; ++k) {          for(i = 2; i + (1 << k) - 1 <= n; ++i) {              rmq[i][k] = min(rmq[i][k - 1],                          rmq[i + (1 << (k - 1))][k - 1]);          }      }  }    int lcp(int a, int b)  {      a = ranks[a], b = ranks[b];      if(a > b)          swap(a, b);      ++a;      int k = (int) (log((b - a + 1) * 1.0) / log(2.0));      return min(rmq[a][k], rmq[b - (1 << k) + 1][k]);  }  int a[N];int main(){int ans=0;while(cin>>s,s[0]!='#'){ans++;int i,j,k,l;int n=strlen(s);for(i=0;i<n;i++)r[i]=s[i];r[n]=0;suffix(n+1,180);calheight(n);initrmq(n);int mx=0,cnt;for(l=1;l<n;l++){for(i=0;i+l<n;i+=l){int t=lcp(i,i+l);int m=t/l+1;//现在的个数int h=l-(t%l);//需要向前移if(i-h>=0 && t%l)if(lcp(i-h,i+l-h)>=t)m++;if(m>mx){mx=m;cnt=0;a[cnt++]=l;}else if(m==mx)a[cnt++]=l;}}int len=-1,st;for(i=1;i<=n&&len==-1;i++){for(j=0;j<cnt;j++){if(lcp(sa[i],sa[i]+a[j])>=(mx-1)*a[j]){len=a[j];st=sa[i];break;}}}int he=len*mx;printf("Case %d: ",ans);for(i=st;i<st+he;i++) printf("%c",r[i]);printf("\n");}}


0 0
原创粉丝点击