zoukankan      html  css  js  c++  java
  • POJ3261(SummerTrainingDay10-G 后缀数组)

    Milk Patterns

    Time Limit: 5000MS   Memory Limit: 65536K
    Total Submissions: 15974   Accepted: 7041
    Case Time Limit: 2000MS

    Description

    Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some regular patterns in the daily milk quality.

    To perform a rigorous study, he has invented a complex classification scheme by which each milk sample is recorded as an integer between 0 and 1,000,000 inclusive, and has recorded data from a single cow over N (1 ≤ N ≤ 20,000) days. He wishes to find the longest pattern of samples which repeats identically at least K (2 ≤ K ≤ N) times. This may include overlapping patterns -- 1 2 3 2 3 2 3 1 repeats 2 3 2 3 twice, for example.

    Help Farmer John by finding the longest repeating subsequence in the sequence of samples. It is guaranteed that at least one subsequence is repeated at least K times.

    Input

    Line 1: Two space-separated integers: N and K 
    Lines 2..N+1: N integers, one per line, the quality of the milk on day i appears on the ith line.

    Output

    Line 1: One integer, the length of the longest pattern which occurs at least K times

    Sample Input

    8 2
    1
    2
    3
    2
    3
    2
    3
    1

    Sample Output

    4

    Source

     
      1 //2017-08-11
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 
      7 using namespace std;
      8 
      9 const int N = 1000010;
     10 const int inf = 0x3f3f3f3f;
     11 char str[N];
     12 int n, r[N], k;
     13 int wa[N], wb[N], wv[N], wss[N];
     14 int Suffix[N];//Str下标为i ~ Len的连续子串(即后缀) 
     15 int SA[N];//满足Suffix[SA[1]] < Suffix[SA[2]] …… < Suffix[SA[Len]],即排名为i的后缀为Suffix[SA[i]](与Rank是互逆运算) 
     16 int Rank[N];//Suffix[i]在所有后缀中的排名 
     17 int Height[N];//height[i]表示Suffix[SA[i]]和Suffix[SA[i-1]]的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀
     18 int H[N];//等于Height[Rank[i]],也就是后缀Suffix[i]和它前一名的后缀的最长公共前缀 
     19 
     20 //比较母串r中起始位置为a和b,长度都为len的子串是否相等
     21 int cmp(int *r, int a, int b, int len)
     22 {
     23     return r[a]==r[b] && r[a+len]==r[b+len];
     24 }
     25 
     26 //倍增算法求SA数组。
     27 void da(int *r, int *SA, int n, int m)
     28 {
     29     int i, j, p, *x = wa, *y = wb, *t;
     30     for(i = 0; i < m; i++)wss[i] = 0;
     31     for(i = 0; i < n; i++)wss[x[i]=r[i]]++;
     32     for(i = 0; i < m; i++)wss[i]+=wss[i-1];
     33     for(i = n-1; i >= 0; i--)SA[--wss[x[i]]]=i;
     34     for(j = 1, p = 1; p < n; j *= 2, m = p){
     35         for(p = 0, i = n-j; i < n; i++)
     36               y[p++] = i;
     37         for(i = 0; i < n; i++)
     38               if(SA[i] >= j)
     39                   y[p++] = SA[i]-j;
     40         for(i = 0; i < n; i++)
     41               wv[i] = x[y[i]];
     42         for(i = 0; i < m; i++)
     43               wss[i] = 0;
     44         for(i = 0; i < n; i++)
     45               wss[wv[i]]++;
     46         for(i = 1; i < m; i++)
     47               wss[i] += wss[i-1];
     48         for(i = n-1; i >= 0; i--)
     49               SA[--wss[wv[i]]] = y[i];
     50         for(t = x, x = y, y = t, p = 1, x[SA[0]]=0, i = 1; i < n; i++)
     51               x[SA[i]] = cmp(y, SA[i-1], SA[i], j)?p-1:p++;
     52     }
     53 }
     54 
     55 //计算height数组
     56 void cal_Height(int *r, int *SA, int n)
     57 {
     58     int i, j, k = 0;
     59     for(i = 1; i <= n; i++)Rank[SA[i]] = i;
     60     for(i = 0; i < n; Height[Rank[i++]] = k)
     61           for(k?k--:0, j=SA[Rank[i]-1]; r[i+k]==r[j+k]; k++)
     62           ;
     63 }
     64 
     65 int st[N][30];
     66 
     67 void init_rmq(int n)
     68 {
     69     for(int i=1;i<=n;i++) st[i][0]=Height[i];
     70     for(int j=1;(1<<j)<=n;j++)
     71         for(int i=1;i+(1<<j)-1<=n;i++)
     72         {
     73             st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
     74         }
     75 }
     76 
     77 //询问后缀i和后缀j的最长公共前缀
     78 int lcp(int i,int j)
     79 {
     80     i = Rank[i];
     81     j = Rank[j];
     82     if(i>j) swap(i,j);
     83     i++;
     84     int k=0;
     85     while(i+(1<<(k+1)) <= j) k++;
     86     return min(st[i][k],st[j-(1<<k)+1][k]);
     87 }
     88 
     89 bool check(int len){
     90     int cnt = 1;
     91     for(int i = 1; i <= n; i++){
     92         if(Height[i] >= len){//将Height进行分组,每组内Height值均大于k。
     93             cnt++;
     94         }else cnt = 1;//重新分组
     95         if(cnt >= k)return true;//一组内元素个数不小于k,说明存在
     96     }
     97     return false;
     98 }
     99 
    100 int main()
    101 {
    102     while(scanf("%d%d", &n, &k)!=EOF)
    103     {
    104         for(int i = 0; i < n; i++)
    105               scanf("%d", &r[i]);
    106         da(r, SA, n+1, 1000010);
    107         cal_Height(r, SA, n);
    108         //二分答案,进行判定
    109         int l = 1, r = n, mid, ans = 0;
    110         while(l <= r){
    111             mid = (l+r)/2;
    112             if(check(mid)){
    113                 ans = mid;
    114                 l = mid+1;
    115             }else r = mid-1;
    116         }
    117         printf("%d
    ", ans);
    118     }
    119 
    120     return 0;
    121 }
  • 相关阅读:
    HTML <form> 标签的 method 属性(20161028)
    PHP数据访问增删查(20161028)
    PHP数据访问基础知识(20161028)
    java代理机制
    java 模拟实现消费者和生产者问题
    Single Number II
    从1到1000中随机取出900个不重复的随机数
    取苹果方式总数
    Net-SNMP(V3协议)安装配置笔记(CentOS 5.2)(转)
    单例模式
  • 原文地址:https://www.cnblogs.com/Penn000/p/7347929.html
Copyright © 2011-2022 走看看