zoukankan      html  css  js  c++  java
  • POJ 1743 Musical Theme

    题目

    给n个数组成的串,求是否有多个“相似”且不重叠的子串的长度大于等于5,两个子串相似当且仅当长度相等且每一位的数字差都相等。

    Input
    The input contains several test cases. The first line of each test case contains the integer N. The following n integers represent the sequence of notes.
    The last test case is followed by one zero.
    Output
    For each test case, the output file should contain a single line with a single integer that represents the length of the longest theme. If there are no themes, output 0.
    Sample Input
    30
    25 27 30 34 39 45 52 60 69 79 69 60 52 45 39 34 30 26 22 18
    82 78 74 70 66 67 64 60 65 80
    0
    Sample Output
    5
    不考虑相似的定义,先考虑相同
    不可重叠最长重复子串
    先求出h数组,二分答案k
    然后分成若干组,每组的h都大于k,如果该区间内Max_SA-Min_SA>=k
    就说明存在长为k的不可重叠最长重复子串
    本题从相同变成"相似"
    其实把原数组差分,这样得出的新串如果有两个长度为n的子串相同,那么它们对应在原串的长度n+1的子串也就相似
    也就转化为求差分数组不可"相交"最长重复子串
    即两个子串至少要隔一个数
    因为如果两个子串靠在一起这样反应到原串那两个子串各自的首尾是重合的
    记得h[i]在最后加一个0,不然最后一组不会统计
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 int s[200001],c[200001],SA[200001],h[200001],n,m,x[200001],y[200001],rank[200001],Max,Min,ans;
      8 void radix_sort()
      9 {int i;
     10   for (i=0;i<m;i++)
     11     c[i]=0;
     12   for (i=0;i<n;i++)
     13     c[x[y[i]]]++;
     14   for (i=1;i<m;i++)
     15     c[i]+=c[i-1];
     16   for (i=n-1;i>=0;i--)
     17     SA[--c[x[y[i]]]]=y[i];
     18 }
     19 void build_SA()
     20 {int i,j,k,p;
     21   for (i=0;i<n;i++)
     22     x[i]=s[i],y[i]=i;
     23   m=1000;
     24   radix_sort();
     25   for (k=1;k<=n;k<<=1)
     26     {
     27       p=0;
     28       for (i=n-k;i<n;i++)
     29     y[p++]=i;
     30       for (i=0;i<n;i++)
     31     if (SA[i]>=k) y[p++]=SA[i]-k;
     32       radix_sort();
     33       p=1;swap(x,y);
     34       x[SA[0]]=0;
     35       for (i=1;i<n;i++)
     36     x[SA[i]]=((y[SA[i]]==y[SA[i-1]])&&((SA[i]+k<n?y[SA[i]+k]:-1)==(SA[i-1]+k<n?y[SA[i-1]+k]:-1)))?p-1:p++;
     37       if (p>=n) break;
     38       m=p;
     39     }
     40   for (i=0;i<n;i++)
     41     rank[SA[i]]=i;
     42   int L=0;
     43   for (i=0;i<n;i++)
     44     if (rank[i]>0)
     45       {
     46     if (L>0) L--;
     47     j=SA[rank[i]-1];
     48     while (i+L<n&&j+L<n&&(s[j+L]==s[i+L])) L++;
     49     h[rank[i]]=L;
     50       }
     51 }
     52 bool check(int mid)
     53 {int i;
     54   Max=-1e9;Min=1e9;
     55   h[n]=0;
     56   for (i=1;i<=n;i++)
     57     {
     58       if (h[i]>=mid)
     59     {
     60       Max=max(max(SA[i],SA[i-1]),Max);
     61       Min=min(min(SA[i],SA[i-1]),Min);
     62     }
     63       else
     64     {
     65       if (Max-Min>mid)
     66         return 1;
     67       Max=-1e9;Min=1e9;
     68     }
     69     }
     70   return 0;
     71 }
     72 int main()
     73 {int i,now,last;
     74   while (cin>>n&&n)
     75     {
     76       scanf("%d",&last);
     77       if (n==1)
     78     {
     79       cout<<0<<endl;
     80       continue;
     81     }
     82       for (i=0;i<n-1;i++)
     83     {
     84       scanf("%d",&now);
     85       s[i]=now-last+88;
     86       last=now;
     87     }
     88       n--;
     89       s[n]=0;
     90       build_SA();
     91       int l=0,r=n/2;
     92       ans=0;
     93       while (l<=r)
     94     {
     95       int mid=(l+r+1)/2;
     96       if (check(mid)) ans=mid,l=mid+1;
     97       else r=mid-1;
     98     }
     99       if (ans<4) printf("0
    ");
    100       else 
    101       printf("%d
    ",ans+1);
    102     }
    103 }
  • 相关阅读:
    【Redis过期Key监听】
    【ElasticSearch】ES线上脏数据处理
    【MySQL】实现线上千万数据表添加字段操作以及缓存刷新
    【转】【堆外内存】堆内内存与堆外内存
    【Redis连接超时】记录线上RedisConnectionFailureException异常排查过程
    【ElasticSearch】ES 读数据,写数据与搜索数据的过程
    【ElasticSearch】shards,replica,index之间的关系
    tomorrow多线程启动
    request接口下载附件
    request接口上传附件
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8479292.html
Copyright © 2011-2022 走看看