zoukankan      html  css  js  c++  java
  • POJ 1743

    题意:
        给出一列数据,问你其中重复的最长连续子串的长度
        但是有要求:
            1. 长度至少为 5 .
            2. 两串可以不相等,但两串每个对应位置的数字相减差值固定 (即相同变化)

    分析:
        因为子串变化相同,故可先把原数组前后相减, 则求出差值数组的最长重复子串的长度再 +1 就是答案.
        
        最长重复子串的长度:
            使用后缀数组.
            先将问题变为判定是否存在长度为 x 的重复子串,再用二分寻找答案.
            用 height数组 将长度大于 x 的划为同区,则每个区里的每个后缀的公共前缀至少为 x
            再找每个区的后缀的 sa 的最大值和最小值,若最大值和最小值之差不小于x,那两个后缀的公共前缀则不重叠,即有解
       

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 const int MAXN = 20010;
     6 struct SuffixArray
     7 {
     8     int wa[MAXN], wb[MAXN], wsf[MAXN], wv[MAXN];
     9     
    10     int Cmp(int r[], int a, int b, int k)
    11     {
    12         return r[a] == r[b] && r[a+k] == r[b+k];
    13     }
    14     void GetSa(int r[], int sa[], int n, int m)
    15     {
    16         int i, j, p, *x = wa, *y = wb, *t;
    17         for (i = 0; i < m; i++)  wsf[i] = 0;
    18         for (i = 0; i < n; i++)  wsf[x[i]=r[i]]++;
    19         for (i = 1; i < m; i++)  wsf[i] += wsf[i-1];
    20         for (i = n-1; i >= 0; i--)  sa[--wsf[x[i]]] = i;
    21         for (p = j = 1; p < n; j *= 2, m = p) {
    22             for (p = 0, i = n - j; i < n; i++)  y[p++] = i;
    23             for (i = 0; i < n; i++)  if(sa[i] >= j)  y[p++] = sa[i] - j;
    24             for (i = 0; i < n; i++)  wv[i] = x[y[i]];
    25             for (i = 0; i < m; i++)  wsf[i] = 0;
    26             for (i = 0; i < n; i++)  wsf[wv[i]]++;
    27             for (i = 1; i < m; i++)  wsf[i] += wsf[i-1];
    28             for (i = n-1; i >= 0; i--)  sa[--wsf[wv[i]]] = y[i];
    29             swap(x, y);
    30             x[sa[0]] = 0;
    31             for (p = i = 1; i < n; i++)
    32                 x[sa[i]] = Cmp(y, sa[i-1], sa[i], j) ? p - 1 : p++;
    33         }
    34     }
    35     void GetHeight(int r[], int sa[], int rnk[], int height[], int n)
    36     {
    37         int i, j, k = 0;
    38         for (i = 1; i <= n; i++)  
    39             rnk[sa[i]] = i;
    40         for (i = 0; i < n; i++)
    41         {
    42             if (k) k--;
    43             j = sa[rnk[i]-1];
    44             while (r[i+k] == r[j+k]) k++;
    45             height[rnk[i]] = k;
    46         }
    47     }
    48 }suffixArray;
    49 int r[MAXN], sa[MAXN], rnk[MAXN], height[MAXN];
    50 int s[MAXN];
    51 int n;
    52 
    53 bool Query(int x)
    54 {
    55     int Min, Max;
    56     Min = Max = sa[1];
    57     for(int i = 2; i < n; i++)
    58     {
    59         if(height[i] >= x)
    60         {
    61             Min = min(Min, sa[i]);
    62             Max = max(Max, sa[i]);
    63             if(Max - Min >= x) return 1;
    64         }
    65         else Min = Max = sa[i];
    66     }
    67     return 0;
    68 }
    69 int solve(int l,int r)
    70 {
    71     int mid,pos;
    72     while(l<=r)
    73     {
    74         int mid=(l+r)>>1;
    75         if(Query(mid)) pos=mid,l=mid+1;
    76         else r=mid-1;
    77     }
    78     return pos;
    79 }
    80 int main()
    81 {
    82     while(~scanf("%d",&n) && n)
    83     {
    84         for (int i = 0; i < n; i++) scanf("%d",&s[i]);
    85         n--;
    86         for (int i = 0; i < n; i++)
    87             r[i] = s[i+1] - s[i] + 100;
    88         r[n] = 0;
    89         suffixArray.GetSa(r,sa,n+1,200);
    90         suffixArray.GetHeight(r,sa,rnk,height,n);
    91         int l = 0, r = n;
    92         int ans = solve(l, r) + 1;
    93         printf("%d
    ", ans < 5 ? 0 : ans);
    94     }
    95 }
    我自倾杯,君且随意
  • 相关阅读:
    List遍历时删除与迭代器(Iterator)解惑
    从一次“并发修改字段业务”引出多版本并发控制与InnoDB锁
    RocketMQ存储机制与确认重传机制
    Java中的锁
    jmeter在non-GUI模式下用法
    Java SPI机制简述
    深拷贝、浅拷贝与Cloneable接口
    Java中的小数运算与精度损失
    java中的枚举类
    SpringBoot是如何实现自动配置的
  • 原文地址:https://www.cnblogs.com/nicetomeetu/p/5763236.html
Copyright © 2011-2022 走看看