zoukankan      html  css  js  c++  java
  • POJ 1743-Musical Theme-后缀数组

    后缀数组国家集训队论文

    论文上讲的很清楚。

    最长不重叠重复子串问题。首先二分答案,对于每一个mid长度,按照后缀的height大于mid对height数组分组。

    可以证明,答案在同一个height当中。维护每一组的最大最小sa值,差便是每一组的最大不重叠重复子串长度。如果大于mid就return true。

    看代码很容易懂

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cstring>
      4 
      5 using namespace std;
      6 
      7 const int maxn = 2e4+10;
      8 int N,save[maxn];
      9 
     10 int s[maxn];
     11 int sa[maxn],t[maxn],t2[maxn],c[maxn];
     12 int rank[maxn],height[maxn];
     13 
     14 void Build(int n,int m)
     15 {
     16     int i,j,*x = t,*y = t2;
     17     for(i=0;i<m;i++) c[i] = 0;
     18     for(i=0;i<n;i++) c[x[i]=s[i] ] ++;
     19     for(i=1;i<m;i++) c[i] += c[i-1];
     20     for(i=n-1;i>=0;i--) sa[--c[x[i] ] ] = i;
     21 
     22     for(int k=1;k<=n;k<<=1)
     23     {
     24         int p = 0;
     25         for(i=n-k;i<n;i++) y[p++] = i;
     26         for(i=0;i<n;i++) if(sa[i]>=k) y[p++] = sa[i]-k;
     27 
     28         for(i=0;i<m;i++) c[i] = 0;
     29         for(i=0;i<n;i++) c[x[y[i] ] ]++;
     30         for(i=1;i<m;i++) c[i] += c[i-1];
     31         for(i=n-1;i>=0;i--) sa[--c[x[y[i] ] ] ] = y[i];
     32 
     33         swap(x,y);
     34         p = 1;x[sa[0] ] = 0;
     35         for(i=1;i<n;i++)
     36             x[sa[i] ] = y[sa[i-1] ]==y[sa[i] ]&&y[sa[i-1]+k ]==y[sa[i]+k ]?p-1:p++;
     37         if(p>=n) break;
     38         m = p;
     39     }
     40     n--;
     41 
     42     int k=0;
     43     for(i=0;i<=n;i++) rank[sa[i]] = i;
     44     for(i=0;i<n;i++)
     45     {
     46         if(k) k--;
     47         j = sa[rank[i]-1 ];
     48         while(s[i+k]==s[j+k]) k++;
     49         height[rank[i] ] = k;
     50     }
     51 }
     52 
     53 bool check(int k,int n)
     54 {
     55     int mx=sa[1],mi=sa[1];
     56     for(int i=2;i<=n;i++)
     57     {
     58         if(height[i] < k)
     59         {
     60             mx = mi = sa[i];
     61         }
     62         else
     63         {
     64             if(sa[i] > mx) mx = sa[i];
     65             if(sa[i] < mi) mi = sa[i];
     66             if(mx-mi > k) return true;
     67         }
     68     }
     69     return false;
     70 }
     71 
     72 int main()
     73 {
     74     while(scanf("%d",&N) && N)
     75     {
     76         for(int i=0;i<N;i++)
     77             scanf("%d",&save[i]);
     78         for(int i=N-1;i>0;i--)
     79             s[i] = save[i] - save[i-1] + 90;
     80         N--;
     81         for(int i=0;i<N;i++) s[i] = s[i+1];
     82         s[N] = 0;
     83 
     84         Build(N+1,200);
     85         int mid,l=1,r = N;
     86         int ans = -1;
     87 
     88         while(l<=r)
     89         {
     90             mid = (l+r)>>1;
     91             if(check(mid,N))
     92             {
     93                 ans = mid;
     94                 l = mid+1;
     95             }
     96             else
     97                 r = mid-1;
     98         }
     99         //printf("ans:%d
    ",ans);
    100         if(mid < 4) printf("0
    ");
    101         else printf("%d
    ",ans+1);
    102     }
    103 }
  • 相关阅读:
    通过DataSet操作XML
    什么是网站流量
    JavaScript总结(2)网页上显示时间
    对xml操作的主要方法
    xml保存图片和读取图片(三)
    SharePoint初探sharepoint 安装宝典(2)
    SharePoint初探启用wss的全文搜索(6)
    转载:sharepoint portal server2003安装小记
    SharePoint初探装完Wss后,无法创建或打开原有Web项目问题(7)
    SharePoint初探SharePoint网站整理(8)
  • 原文地址:https://www.cnblogs.com/helica/p/5506543.html
Copyright © 2011-2022 走看看