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

    1743:Musical Theme

    链接

    题意

      给一个序列,找两个子串,满足:

    • 长度至少为5
    • 相同或者转置后相同(转置:序列每个数字加减相同的数字后变成的序列)
    • 两个子串不能有公共部分。

    思路

      对于第二个条件,就是差分后相同(奇妙的转化)。那么就是求一个串的出现2次,不可重叠的最长的子串。

      后缀数组,二分一个长度x,判断是否满足。

      判断:可以height划分成多个子段(每个子段是连续的一段序列且所有的height的值都要>x),那么对于每个子段的中对应的后缀任意两个都满足公共子串>x,所以在当前子段中找到最左边的点,和最右边的点,要求判断是否重叠(即r-l>x)。

    代码

     1 #include<cstdio>
     2 #include<algorithm>
     3 
     4 using namespace std;
     5 
     6 const int N = 20010;
     7 
     8 int t1[N],t2[N],c[N],height[N],rnk[N],sa[N],s[N],a[N];
     9 int n,m;
    10 
    11 void get_sa() {
    12     m = 180;
    13     int *x = t1,*y = t2,p,i;
    14     for (i=0; i<m; ++i) c[i] = 0;
    15     for (i=0; i<n; ++i) x[i]=s[i],c[x[i]]++;
    16     for (i=1; i<m; ++i) c[i] += c[i-1];
    17     for (i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
    18     for (int k=1; k<=n; k<<=1) {
    19         p = 0;
    20         for (i=n-k; i<n; ++i) y[p++] = i;
    21         for (i=0; i<n; ++i) if (sa[i]>=k) y[p++] = sa[i]-k;
    22         for (i=0; i<m; ++i) c[i] = 0;
    23         for (i=0; i<n; ++i) c[x[y[i]]]++;
    24         for (i=0; i<m; ++i) c[i] += c[i-1];
    25         for (i=n-1; i>=0; --i) sa[--c[x[y[i]]]] = y[i];
    26         swap(x,y);
    27         p = 1;
    28         x[sa[0]] = 0;
    29         for (i=1; i<n; ++i) 
    30             x[sa[i]] = (y[sa[i-1]]==y[sa[i]] && sa[i-1]+k<n && sa[i]+k<n &&    y[sa[i-1]+k]==y[sa[i]+k]) ? p-1 : p++;
    31         if (p >= n) break;
    32         m = p;
    33     }
    34 }
    35 void get_height() {
    36     for (int i=0; i<n; ++i) rnk[sa[i]] = i;
    37     int k = 0;
    38     height[0] = 0;
    39     for (int i=0; i<n; ++i) {
    40         if (!rnk[i]) continue;
    41         if (k) k--;
    42         int j = sa[rnk[i]-1];
    43         while (i+k<n  && j+k<n && s[i+k]==s[j+k]) k++;
    44         height[rnk[i]] = k;
    45     }
    46 }
    47 bool check(int x) {
    48     int l = sa[0],r = sa[0];
    49     for (int i=1; i<n; ++i) {
    50         if (height[i] < x) l = r = sa[i];
    51         else {
    52             l = min(l,sa[i]);r = max(r,sa[i]);
    53             if (r - l >= x) return true; // r-l 不是r-l+1,模拟一下 
    54         }
    55     }
    56     return false;
    57 }
    58 void solve() {
    59     int L = 1,R = n/2,ans = -1;
    60     while (L <= R) {
    61         int mid = (L + R) / 2;
    62         if (check(mid)) ans = mid,L = mid + 1;
    63         else R = mid - 1; 
    64     }
    65     if (ans < 4) puts("0");
    66     else printf("%d
    ",ans+1);
    67 }
    68 int main() {
    69     while (~scanf("%d",&n) && n){
    70         for (int i=0; i<n; ++i) scanf("%d",&a[i]);
    71         for (int i=1; i<n; ++i) s[i] = a[i] - a[i-1] + 88;
    72         get_sa();
    73         get_height();
    74         solve();
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    python参考手册--第3章类型和对象
    python参考手册--第2章词汇和语法约定
    Kafka 分布式环境搭建
    常用sql语句
    ValueError: Attempted relative import in non-package
    mysql查询缓存
    secureCRT配色
    mysql deadlock处理
    How to Cope with Deadlocks
    ajax同步
  • 原文地址:https://www.cnblogs.com/mjtcn/p/8989703.html
Copyright © 2011-2022 走看看