zoukankan      html  css  js  c++  java
  • 4698. [SDOI2008]Sandy的卡片【后缀数组】

    Description

    Sandy和Sue的热衷于收集干脆面中的卡片。然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积
    攒卡片兑换超炫的人物模型。每一张卡片都由一些数字进行标记,第i张卡片的序列长度为Mi,要想兑换人物模型
    ,首先必须要集够N张卡片,对于这N张卡片,如果他们都有一个相同的子串长度为k,则可以兑换一个等级为k的人
    物模型。相同的定义为:两个子串长度相同且一个串的全部元素加上一个数就会变成另一个串。Sandy的卡片数远
    远小于要求的N,于是Sue决定在Sandy的生日将自己的卡片送给Sandy,在Sue的帮助下,Sandy终于集够了N张卡片
    ,但是,Sandy并不清楚他可以兑换到哪个等级的人物模型,现在,请你帮助Sandy和Sue,看看他们最高能够得到
    哪个等级的人物模型。

    Input

    第一行为一个数N,表示可以兑换人物模型最少需要的卡片数,即Sandy现在有的卡片数
    第i+1行到第i+N行每行第一个数为第i张卡片序列的长度Mi,之后j+1到j+1+Mi个数,用空格分隔,分别表示序列中
    的第j个数
    n<=1000,M<=1000,2<=Mi<=101

    Output

    一个数k,表示可以获得的最高等级。
     

    Sample Input

    2
    2 1 2
    3 4 5 9

    Sample Output

    2
     
    emmmm一道非常难受的后缀数组
    一共三步但只想到了前两步(最弱智的一步没有想出来……)
    首先把相邻数的所有差值连起来做一个SA ,设不同卡片为不同颜色
    然后二分长度,看有没有一个SA区间公共前缀大于该长度并且涵盖所有颜色即为满足
    求公共前缀的时候若该后缀的前缀跨越两个颜色是不合法的(在这里被坑了)
     
      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #define MAXN (1000000+10)
      5 using namespace std;
      6 int n,m=2050,t,h,maxn;
      7 int r[MAXN],a[MAXN],Col[MAXN];
      8 int SA[MAXN],Rank[MAXN],Height[MAXN];
      9 int wt[MAXN],wa[MAXN],wb[MAXN];
     10 int stack[MAXN],top;
     11 bool used[MAXN];
     12 
     13 bool cmp(int *y,int a,int b,int k)
     14 {
     15     int arank1=y[a];
     16     int brank1=y[b];
     17     int arank2=a+k>=n?-1:y[a+k];
     18     int brank2=b+k>=n?-1:y[b+k];
     19     return arank1==brank1 && arank2==brank2;
     20 }
     21 
     22 void Build_SA()
     23 {
     24     int *x=wa,*y=wb;
     25     for (int i=0;i<m;++i) wt[i]=0;
     26     for (int i=0;i<n;++i) wt[x[i]=r[i]]++;
     27     for (int i=1;i<m;++i) wt[i]+=wt[i-1];
     28     for (int i=n-1;i>=0;--i) SA[--wt[x[i]]]=i; 
     29     
     30     for (int j=1;j<=n;j<<=1)
     31     {
     32         int p=0;
     33         for (int i=n-j;i<n;++i) y[p++]=i;
     34         for (int i=0;i<n;++i) if (SA[i]>=j) y[p++]=SA[i]-j;
     35     
     36         for (int i=0;i<m;++i) wt[i]=0;
     37         for (int i=0;i<n;++i) wt[x[y[i]]]++;
     38         for (int i=1;i<m;++i) wt[i]+=wt[i-1];
     39         for (int i=n-1;i>=0;--i) SA[--wt[x[y[i]]]]=y[i];
     40         
     41         m=1;swap(x,y);
     42         x[SA[0]]=0;
     43         for (int i=1;i<n;++i) 
     44             x[SA[i]]=cmp(y,SA[i],SA[i-1],j)?m-1:m++;
     45         if (m>=n) break;
     46     }
     47 }
     48 
     49 void Build_Height()
     50 {
     51     for (int i=0;i<n;++i) Rank[SA[i]]=i;
     52     int k=0;
     53     Height[0]=0;
     54     for (int i=0;i<n;++i)
     55     {
     56         if (!Rank[i]) continue;
     57         int j=SA[Rank[i]-1];
     58         if (k) k--;
     59         while (r[i+k]==r[j+k]) k++;
     60         Height[Rank[i]]=k;
     61     }
     62 }
     63 
     64 bool check(int len)
     65 {
     66     int sum=0;
     67     for (int i=0;i<n;++i) 
     68     {
     69         if (Height[i]<len)
     70         {
     71             sum=0;
     72             while (top) 
     73                 used[stack[top--]]=false;
     74         }
     75         if (!used[Col[SA[i]]] && Col[SA[i]]==Col[SA[i]+len-1])
     76         {
     77             used[Col[SA[i]]]=true;
     78             sum++;
     79             stack[++top]=Col[SA[i]];
     80         }
     81         if (sum==t) return true;
     82     }
     83     return false;
     84 }
     85 
     86 int main()
     87 {
     88     scanf("%d",&t);
     89     for (int i=1;i<=t;++i)
     90     {
     91         scanf("%d",&h);
     92         maxn=max(maxn,h);
     93         for (int j=1;j<=h;++j)
     94         {
     95             scanf("%d",&a[j]);
     96             if (j==1) continue;
     97             r[n++]=a[j]-a[j-1]+510;
     98             Col[n-1]=i;
     99         }
    100     }
    101     Build_SA();
    102     Build_Height();
    103     int l=0,r=105;
    104     while (l<r)
    105     {
    106         int mid=(l+r+1)>>1;
    107         if (check(mid))
    108             l=mid;
    109         else
    110             r=mid-1;
    111     }
    112     printf("%d",l+1);
    113 }
  • 相关阅读:
    poj1014 Dividing (多重背包)
    HDOJ 1316 How Many Fibs?
    最大字串和
    WHY IE AGAIN?
    Codeforces Round #143 (Div. 2) (ABCD 思维场)
    自用组帧工具
    菜鸟学EJB(二)——在同一个SessionBean中使用@Remote和@Local
    shell 块注释
    检测到在集成的托管管道模式下不适用的 ASP.NET 设置的解决方法
    Windows Myeclipse 10 安装 Perl 插件
  • 原文地址:https://www.cnblogs.com/refun/p/8679191.html
Copyright © 2011-2022 走看看