zoukankan      html  css  js  c++  java
  • poj 1743 二分答案+后缀数组 求不重叠的最长重复子串

    题意:给出一串序列,求最长的theme长度

    (theme:完全重叠的子序列,如1 2 3和1 2 3  or  子序列中每个元素对应的差相等,如1 2 3和7 8 9)

    要是没有差相等这个条件那就好办多了,直接裸题。

    一开始想了个2B方法,后来发现真心2B啊蛤蛤蛤

     1 for i=1 to 88 do
     2 {
     3     for j=1 to length
     4     {
     5         r2[j]=r[j]+i;
     6         if (r2[j]>88)    r2[i]-=88;
     7     }
     8     把新序列r2连接到原序列r的后面
     9     process[r+r2]
    10     .....
    11     求for i=1->88中得到的最大答案    
    12 }
    View Code

    正解:http://bbezxcy.iteye.com/blog/1407395

    对原序列相邻两元素作差就行了= =

    比如:序列8 8 8 15 24 3 3 3

    作差得到0 0 7 9 -21 0 0

    对新序列再求最长不重叠重复子串,得到的结果+1,就是原序列的最长不重叠重复子串

    求最长不重叠重复子串:参考IOI2009论文

    Code:

      1 #include "stdio.h"
      2 #include "string.h"
      3 #define maxn 20010
      4 
      5 int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
      6 int rank[maxn],height[maxn];
      7 int r[maxn],sa[maxn],ans[maxn];
      8 int n;
      9 
     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 da(int *r,int *sa,int n,int m)
     17 {
     18     int i,j,p,*x=wa,*y=wb,*t;
     19     for(i=0; i<m; i++) ws[i]=0;
     20     for(i=0; i<n; i++) ws[x[i]=r[i]]++;
     21     for(i=1; i<m; i++) ws[i]+=ws[i-1];
     22     for(i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;
     23     for(j=1,p=1; p<n; j*=2,m=p)
     24     {
     25 
     26         for(p=0,i=n-j; i<n; i++) y[p++]=i;
     27         for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
     28         for(i=0; i<n; i++) wv[i]=x[y[i]];
     29         for(i=0; i<m; i++) ws[i]=0;
     30         for(i=0; i<n; i++) ws[wv[i]]++;
     31         for(i=1; i<m; i++) ws[i]+=ws[i-1];
     32         for(i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i];
     33         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)
     34             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
     35     }
     36     return;
     37 }
     38 
     39 void calheight(int *r,int *sa,int n)
     40 {
     41     int i,j,k=0;
     42     for(i=1; i<=n; i++) rank[sa[i]]=i;
     43     for(i=0; i<n; height[rank[i++]]=k)
     44         for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
     45     return;
     46 }
     47 
     48 bool calc(int x)
     49 {
     50     int nm=0;
     51     for (int i=1;i<=n;i++)
     52         if (height[i]<x)
     53         {
     54             nm++;
     55             ans[nm]=i;
     56         }
     57     nm++;
     58     ans[nm]=n+1;
     59     for (int i=0;i<nm;i++)
     60     {
     61         int tl=ans[i],tr=ans[i+1]-1;
     62         int tn=maxn,tx=0;
     63         for (int j=tl;j<=tr;j++)
     64         {
     65             if (tn>sa[j])   tn=sa[j];
     66             if (tx<sa[j])   tx=sa[j];
     67         }
     68         if (tx-tn>=x)   return true;
     69     }
     70     return false;
     71 }
     72 
     73 //da(r,sa,n+1,128);
     74 //calheight(r,sa,n);
     75 int main()
     76 {
     77 //    freopen("in.txt","r",stdin);
     78     while (~scanf("%d",&n))
     79     {
     80         if (n!=0)
     81         {
     82             memset(sa,0,sizeof(sa));
     83             memset(height,0,sizeof(height));
     84             memset(ans,0,sizeof(ans));
     85 
     86             for (int i=0; i<n; i++)
     87                 scanf("%d",&r[i]);
     88             r[n]=0;
     89 
     90 //          for (int i=0;i<=n;i++)
     91 //              printf("%d ",r[i]);
     92 //          printf("
     %d
    ",n);
     93 
     94             for (int i=1;i<n;i++)
     95                 r[i-1]=r[i]-r[i-1];
     96             n--;
     97             r[n]=0;
     98 
     99             for (int i=0;i<n;i++)
    100                 r[i]+=100;
    101 
    102 //          for (int i=0;i<=n;i++)
    103 //              printf("%d ",r[i]);
    104 //          printf("
     %d
    ",n);
    105 
    106             da(r,sa,n+1,200);
    107             calheight(r,sa,n);
    108 
    109 //          for (int i=0; i<=n; i++)
    110 //              printf("%d  %d
    ",sa[i],height[i]);
    111 //          printf("
    ");
    112 
    113             int l=maxn,r=0,res=0;
    114             for (int i=1;i<=n;i++)
    115             {
    116                 if (height[i]<l)   l=height[i];
    117                 if (height[i]>r)   r=height[i];
    118             }
    119             while (r>=l)
    120             {
    121                 int mid=(l+r)/2;
    122                 if (calc(mid))
    123                 {
    124                     l=mid+1;
    125                     res=mid;
    126                 }
    127                 else
    128                     r=mid-1;
    129             }
    130             res++;
    131             if (res<5)  res=0;
    132             printf("%d
    ",res);
    133         }
    134     }
    135     return 0;
    136 }
    View Code

    本题出自USACO5.1 theme,据说是男人八题之一.....orz

  • 相关阅读:
    P3932 浮游大陆的68号岛
    P4595 [COCI2011-2012#5] POPLOCAVANJE
    CF455E Function
    【转载】乱堆的东西
    BZOJ1034 [ZJOI2008]泡泡堂BNB[贪心]
    CSP2019退役记
    BZOJ5206 [Jsoi2017]原力[根号分治]
    luogu3651 展翅翱翔之时 (はばたきのとき)[基环树+贪心]
    BZOJ1040 [ZJOI2008]骑士[基环树DP]
    BZOJ3037 创世纪[基环树DP]
  • 原文地址:https://www.cnblogs.com/pdev/p/4043636.html
Copyright © 2011-2022 走看看