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

    题目大意

    找到一个连续的子序列连续出现过两次,且这两次不相交,只要子序列中每个数都加/减一个数得到一个新的序列,也可以看作是相同的

    那么也就是说这道题目可以转化成找到两个子序列,这两个子序列中每个数前后的差值是相等的

    所以我们可以求所有数两两之间的差值,然后根据这个值建立后缀数组后,二分答案来解决问题

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 
     5 using namespace std;
     6 const int N = 20010;
     7 int rank[N] , sa[N] , height[N];
     8 int wa[N] , wb[N] , tmp[N] , wv[N];
     9 int a[N] , b[N];
    10 
    11 int cmp(int *r , int a , int b , int l)
    12 {
    13     return r[a]==r[b] && r[a+l]==r[b+l];
    14 }
    15 
    16 void getSa(int *r , int *sa , int n , int m)
    17 {
    18     int i,j,p;
    19     int *x=wa , *y=wb , *t;
    20     for(i=0 ; i<m ; i++) tmp[i]=0;
    21     for(i=0 ; i<n ; i++) tmp[x[i]=r[i]]++;
    22     for(i=1 ; i<m ; i++) tmp[i]+=tmp[i-1];
    23     for(i=n-1 ; i>=0 ; i--) sa[--tmp[x[i]]]=i;
    24 
    25     //初始p=1是防止只有一个元素就可以退出循环的
    26     for(p=1,j=1 ; p<n ; j*=2,m=p){
    27         //对第二关键字排序
    28         p=0;
    29         for(i=n-j ; i<n ; i++) y[p++]=i;
    30         for(i=0 ; i<n ; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
    31 
    32         for(i=0 ; i<n ; i++) wv[i]=x[y[i]];
    33         for(i=0 ; i<m ; i++) tmp[i]=0;
    34         for(i=0 ; i<n ; i++) tmp[wv[i]]++;
    35         for(i=1 ; i<m ; i++) tmp[i]+=tmp[i-1];
    36         for(i=n-1 ; i>=0 ; i--) sa[--tmp[wv[i]]]=y[i];
    37         t=x,x=y,y=t;
    38         x[sa[0]]=0;
    39         for(p=1,i=1 ; i<n ; i++)
    40             x[sa[i]] = cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    41     }
    42 
    43     return;
    44 }
    45 
    46 void callHeight(int *r,int *sa,int n)
    47 {
    48     int i,j,k=0;
    49     for(i=1 ; i<=n ; i++) rank[sa[i]]=i;
    50 
    51     for(i=0 ; i<n ; height[rank[i++]]=k)
    52         for(k?k--:0 , j=sa[rank[i]-1] ; r[i+k]==r[j+k] ; k++);
    53     return;
    54 }
    55 
    56 bool check(int m , int n)
    57 {
    58     int l=sa[0] , r=sa[0];
    59     for(int i=1 ; i<n ; i++){
    60         if(height[i]<m){
    61             l=sa[i] , r=sa[i];
    62         }
    63         else{
    64             l=min(sa[i] , l);
    65             r=max(sa[i] , r);
    66             if(r-l>m) return true;
    67         }
    68     }
    69     return false;
    70 }
    71 
    72 int main()
    73 {
    74   //  freopen("a.in" , "r" , stdin);
    75     int n;
    76     while(scanf("%d" , &n) , n)
    77     {
    78         for(int i=0 ; i<n ; i++) scanf("%d" , &a[i]);
    79         for(int i=0 ; i<n-1 ; i++) b[i]=a[i+1]-a[i]+90;
    80         b[n-1]=0;
    81         getSa(b,sa,n,200);
    82         callHeight(b,sa,n-1);
    83 
    84         int l=0 , r=n , ans=0;
    85         while(l<=r){
    86             int m=(l+r)>>1;
    87             if(!check(m,n))  r=m-1;
    88             else{
    89                 ans=m;
    90                 l=m+1;
    91             }
    92         }
    93         if(ans>=4) printf("%d
    " , ans+1);
    94         else puts("0");
    95     }
    96     return 0;
    97 }
  • 相关阅读:
    umask设置导致的weblogic中的应用上传的文件没有权限打开
    顺序表查找及其优化(Java)
    前端能力要求
    CSS动画:旋转卡片效果
    CSS居中
    http服务器与https服务器的区别
    phpCURL抓取网页内容
    Node.js概述
    jQuery源码分析
    JavaScript学习书签
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4388805.html
Copyright © 2011-2022 走看看