• [Poj1743] [后缀数组论文例题] Musical Theme [后缀数组不可重叠最长重复子串]


    利用后缀数组,先对读入整数处理str[i]=str[i+1]-str[i]+90这样可以避免负数,计算Height数组,二分答案,如果某处H<lim则将H数组分开,最终分成若干块,判断每块中是否存在SA[i]-SA[j]>lim(注意不是>=因为查分后如果相等那么两个公共串连接部分的元素是公用的,不符合题意),注意特判n=1的情况,因为查分后的结果是个空串,会导致RE。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <algorithm>
      6 #include <cmath>
      7 #include <ctime>
      8 
      9 using namespace std;
     10 
     11 int    A[21000],B[21000],U[21000],SA[21000],H[21000];
     12 int    str[21000];
     13 
     14 void    Calc_H(const int n,const int * Rank)
     15 {
     16     int    i,j,k=0;
     17     for(i=0;i<n;H[Rank[i++]]=k)
     18         for(k?k--:0,j=SA[Rank[i]-1];str[i+k]==str[j+k];++k);
     19     return ;
     20 }
     21 
     22 bool    cmp(const int * s,const int a,const int b,const int l)
     23 {
     24     return    s[a]==s[b] && s[a+l]==s[b+l];
     25 }
     26 
     27 int*    Get_SA(const int n,int m)
     28 {
     29     int    i,j,p,*x=A,*y=B;
     30     memset(U,0,sizeof(U));
     31     for(i=0;i<n;++i)U[x[i]=str[i]]++;
     32     for(i=1;i<m;++i)U[i]+=U[i-1];
     33     for(i=n-1;i>=0;--i)SA[--U[x[i]]]=i;
     34 
     35     for(j=1,p=1;p<n;j<<=1,m=p)
     36     {
     37         for(p=0,i=n-j;i<n;i++)y[p++]=i;
     38         for(i=0;i<n;++i)if(SA[i]>=j)y[p++]=SA[i]-j;
     39         for(i=0;i<m;++i)U[i]=0;
     40         for(i=0;i<n;++i)U[x[y[i]]]++;
     41         for(i=1;i<m;++i)U[i]+=U[i-1];
     42         for(i=n-1;i>=0;--i)SA[--U[x[y[i]]]]=y[i];
     43         for(swap(x,y),p=1,x[SA[0]]=0,i=1;i<n;++i)
     44             x[SA[i]]=cmp(y,SA[i-1],SA[i],j)?p-1:p++;
     45     }
     46     Calc_H(n,x);
     47     return x;
     48 }
     49 
     50 bool    Check(const int lim,const int n)
     51 {
     52     int    Min=SA[1],Max=SA[1];
     53     for(int i=1;i<=n;++i)
     54     {
     55         if(i>1 && H[i]<lim)
     56         {
     57             if(Max-Min>=lim+1)return true;
     58             Min=0x7fffffff;
     59             Max=-1;
     60         }
     61         if(SA[i]<Min)Min=SA[i];
     62         if(SA[i]>Max)Max=SA[i];
     63     }
     64     if(Max-Min>lim)return true;
     65     return false;
     66 }
     67 
     68 void    Init()
     69 {
     70     memset(A,0,sizeof(A));
     71     memset(B,0,sizeof(B));
     72     memset(U,0,sizeof(U));
     73     memset(H,0,sizeof(H));
     74     memset(SA,0,sizeof(SA));
     75     return ;
     76 }
     77 
     78 int main()
     79 {
     80     int    n,i,l,r;
     81 
     82     while(~scanf("%d",&n) && n)
     83     {
     84         Init();
     85         for(i=0;i<n;++i)scanf("%d",&str[i]);
     86         if(n==1){printf("0
    ");continue;}
     87         n--;
     88         for(i=0;i<n;++i)str[i]=str[i+1]-str[i]+90;
     89         str[n]=0;
     90 
     91         Get_SA(n+1,200);
     92 
     93         l=0,r=n;
     94         while(l<r-1)
     95         {
     96             int    mid=l+((r-l)>>1);
     97             if(Check(mid,n))l=mid;
     98             else        r=mid;
     99         }
    100         printf("%d
    ",l>=4 ? l+1:0);
    101     }
    102 
    103     return 0;
    104 }
    View Code
  • 相关阅读:
    cuda(2)---方阵乘法
    cuda(1)-imageBlur
    python(6) 字符串操作
    CUDA 编程之Release模式和Debug模式
    20200909 day4 刷题记录
    20200908 day3 刷题记录
    20200906 day1 模拟(一)
    刷题Day 4-6 树形dp三题
    4.28 刷题Day 3 树形dp一题
    DTQ2019-D1T2 括号树 题解
  • 原文地址:https://www.cnblogs.com/Gster/p/4977960.html
Copyright © 2020-2023  润新知