现在的位置: 首页 > 综合 > 正文

Sandy 的卡片 card

2018年01月15日 ⁄ 综合 ⁄ 共 3585字 ⁄ 字号 评论关闭

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

【输入文件】
第一行为一个数N,表示可以兑换人物模型最少需要的卡片数,即Sandy 现在有的
卡片数
第i+1 行到第i+N 行每行第一个数为第i 张卡片序列的长度Mi,之后j+1 到j+1+Mi
个数,用空格分隔,分别表示序列中的第j 个数
【输出文件】
一个数k,表示可以获得的最高等级。
【样例】
输入样例:
2
2 1 2
3 4 5 9
输出样例:
2
【数据范围】
30%的数据保证n<=50
100%的数据保证n<=1000

100%的数据保证m[i]<=101

山东省选08年第二轮第一天试题

后缀数组求解

最小的当然是1了

将序列上两项之间的差为内容生成后缀数组

两个各不同序列之间用-maxlongint的来分隔

之后二分答案

按二分的答案将后缀分组

若一组中出现了所有的序列,则该答案成立

测试数据

http://mail.qq.com/cgi-bin/ftnExs_download?k=773535621076cf9e6412407d1a31044e000505520501014e1e530655565550020718540004041c550651054f540653041c070207055509540357055050313961525447061b4350133173&t=exs_ftn_download&code=155b511a

program card;
var
  n,i,j,k,tot,m,max,all,s,e,mid,temp,last:longint;
  dl,root,belong:array [0..110001] of longint;
  change,total,rank,sa,now,keep,height:array [-1..110001] of longint;
  yes:array [0..1001] of boolean;
  xl:array [0..1001] of longint;
  ok:boolean;

function search (mid:longint):boolean;
begin
  if mid=0 then exit(true);
  fillchar(yes,sizeof(yes),false);
  k:=1;
  yes[belong[sa[n+1]]]:=true;
  all:=1;
  xl[1]:=belong[sa[n+1]];
  for i:=n+2 to tot do
    begin
      if height[i]<mid then
        begin
          while all<>0 do
            begin
              yes[xl[all]]:=false;
              dec(all);
            end;
          all:=1;
          xl[1]:=belong[sa[i]];
          yes[belong[sa[i]]]:=true;
          k:=1;
          continue;
        end;
      if not yes[belong[sa[i]]] then
        begin
          yes[belong[sa[i]]]:=true;
          inc(all);
          xl[all]:=belong[sa[i]];
          inc(k);
        end;
      if k=n then exit(true);
    end;
  exit(false);
end;

procedure swap (var a,b:longint);
var
  i:longint;
begin
  i:=a;
  a:=b;
  b:=i;
end;

procedure qsort (s,e:longint);
var
  i,j,k:longint;
begin
  if s>=e then exit;
  i:=s;
  j:=e;
  k:=dl[(s+e) div 2];
  while i<=j do
    begin
      while root[dl[i]]<root[k] do inc(i);
      while root[dl[j]]>root[k] do dec(j);
      if i>j then break;
      swap(dl[i],dl[j]);
      inc(i);
      dec(j);
    end;
  qsort(s,j);
  qsort(i,e);
end;

begin
  assign(input,'card.in');
  reset(input);
  assign(output,'card.out');
  rewrite(output);
  read(n);
  max:=maxlongint;
  tot:=0;
  for i:=1 to n do
    begin
      read(m);
      if m<max then max:=m;
      if m<>0 then read(last);
      for j:=tot + 1 to tot+m-1 do
        begin
          read(temp);
          root[j]:=temp-last;
          last:=temp;
          belong[j]:=i;
        end;
      tot:=tot+m;
      root[tot]:=-maxlongint;
    end;
  for i:=1 to tot do
    dl[i]:=i;
  qsort(1,tot);
  k:=1;
  for i:=1 to tot do
    begin
      if root[dl[i]]<>root[dl[k]] then k:=i;
      rank[dl[i]]:=k;
    end;
  k:=0;
  while 1 shl k<tot do
    begin
      for i:=1 to tot do
        if i+(1 shl k)>tot then change[i]:=0
                           else change[i]:=rank[i+(1 shl k)];
      fillchar(total,sizeof(total),0);
      for i:=1 to tot do
        inc(total[change[i]]);
      for i:=1 to tot do
        total[i]:=total[i]+total[i-1];
      for i:=1 to tot do
        begin
          inc(total[change[i]-1]);
          dl[total[change[i]-1]]:=i;
        end;
      fillchar(total,sizeof(total),0);
      ok:=true;
      for i:=1 to tot do
        begin
          inc(total[rank[i]]);
          if total[rank[i]]=2 then ok:=false;
        end;
      if ok then break;
      for i:=2 to tot do
        total[i]:=total[i]+total[i-1];
      fillchar(now,sizeof(now),0);
      fillchar(keep,sizeof(keep),0);
      for i:=1 to tot do
        begin
          if now[rank[dl[i]]]<>change[dl[i]] then
            begin
              now[rank[dl[i]]]:=change[dl[i]];
              total[rank[dl[i]]-1]:=total[rank[dl[i]]-1]+keep[rank[dl[i]]];
              keep[rank[dl[i]]]:=0;
            end;
          inc(keep[rank[dl[i]]]);
          rank[dl[i]]:=total[rank[dl[i]]-1]+1;
        end;
      inc(k);
    end;
  for i:=1 to tot do
    sa[rank[i]]:=i;
  fillchar(height,sizeof(height),0);
  for i:=1 to tot do
    begin
      if rank[i]=1 then continue;
      k:=height[rank[i-1]]-1;
      if k<0 then k:=0;
      while (i+k<=tot)and(sa[rank[i]-1]+k<=tot)
      and(root[i+k]=root[sa[rank[i]-1]+k]) do inc(k);
      height[rank[i]]:=k;
    end;
  if max<=1 then
    begin
      writeln(max);
      close(input);
      close(output);
      exit;
    end;
  s:=1;
  e:=max;
  while s<>e do
    begin
      mid:=s+e-(s+e) div 2;
      if search(mid-1) then s:=mid
                       else e:=mid-1;
    end;
  writeln(s);
  close(input);
  close(output);
end.


【上篇】
【下篇】

抱歉!评论已关闭.