[BZOJ2754] [SCOI2012]喵星球上的点名解题报告|后缀数组

  

  a180285幸运地被选做了地球到喵星球的留学生。他发现喵星人在上课前的点名现象非常有趣。   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成。喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么这个喵星人就必须答到。 然而,由于喵星人的字码过于古怪,以至于不能用ASCII码来表示。为了方便描述,a180285决定用数串来表示喵星人的名字。

现在你能帮助a180285统计每次点名的时候有多少喵星人答到,以及M次点名结束后每个喵星人答到多少次吗?

  应该算是后缀数组比较简单的应用了吧...

  首先把所有的串都接起来,中间用不同的分隔符隔开

  然后进行后缀数组将sa,rank,height等数组求出来

  最后枚举每一个点名串,以rank[点名串起点]开始向左和向右拓展

  这里的拓展是指在sa的下标里拓展

  边统计边累计每个喵星人的点到次数

  为了避免一次点名中统计到一个喵星人多次,以及一个喵星人一次点名却统计了多次

  (实际上二者是一样的...)

  都可以用一个标号数组来处理

  然而这个标号数组如果每次fillchar显然不现实...因为太慢...

  然后就运用到KM算法里顶标更新的思想

  当然,再做一次然后把数组还原也是可以的

  另外在BZ上PE了一发...行末注意不能留有空格

  1 program bzoj2754;
  2 const INF = 100007;maxn = 400010;
  3 var tota,totb,i,cnt,n,x,j:longint;
  4     a,rank,s,tmp,sa,height,pos,ter,len,vis,ans:array[-1..maxn]of longint;
  5
  6 function max(a,b:longint):longint;
  7 begin
  8     if a>b then exit(a) else exit(b);
  9 end;
 10
 11 procedure Suffix_Array;
 12 var sz,i,j,p,v0,v1,v00,v01:longint;
 13 begin
 14     sz:=max(n,INF+10000);
 15     for i:=0 to sz do s[i]:=0;
 16     for i:=0 to n-1 do rank[i]:=a[i];
 17     for i:=0 to n-1 do inc(s[rank[i]]);
 18     for i:=1 to sz do inc(s[i],s[i-1]);
 19     for i:=n-1 downto 0 do
 20     begin
 21         dec(s[rank[i]]);
 22         sa[s[rank[i]]]:=i;
 23     end;
 24     j:=1;
 25     while j<=n do
 26     begin
 27         p:=0;
 28         for i:=n-j to n-1 do
 29         begin
 30             tmp[p]:=i;inc(p);
 31         end;
 32         for i:=0 to n-1 do if sa[i]-j>=0 then
 33         begin
 34             tmp[p]:=sa[i]-j;inc(p);
 35         end;
 36         for i:=0 to sz do s[i]:=0;
 37         for i:=0 to n-1 do inc(s[rank[i]]);
 38         for i:=1 to sz do inc(s[i],s[i-1]);
 39         for i:=n-1 downto 0 do
 40         begin
 41             dec(s[rank[tmp[i]]]);
 42             sa[s[rank[tmp[i]]]]:=tmp[i];
 43         end;
 44         p:=0;tmp[sa[0]]:=0;
 45         for i:=1 to n-1 do
 46         begin
 47             v0:=sa[i-1];v1:=sa[i];
 48             if v0+j<n then v00:=rank[v0+j] else v00:=-1;
 49             if v1+j<n then v01:=rank[v1+j] else v01:=-1;
 50             if (rank[v0]=rank[v1])and(v00=v01) then tmp[sa[i]]:=p else
 51             begin
 52                 inc(p);tmp[sa[i]]:=p;
 53             end;
 54         end;
 55         for i:=0 to n-1 do rank[i]:=tmp[i];
 56         j:=j << 1;
 57     end;
 58 end;
 59
 60 function compare(i,j,x:longint):longint;
 61 begin
 62     while (i+x-1<n)and(j+x-1<n)and(a[i+x-1]=a[j+x-1]) do inc(x);
 63     exit(x-1);
 64 end;
 65
 66 procedure calc_height;
 67 var i:longint;
 68 begin
 69     if rank[0]=0 then height[0]:=0 else height[0]:=compare(0,sa[rank[0]-1],1);
 70     for i:=1 to n-1 do
 71     if rank[i]=0 then height[i]:=0 else height[i]:=compare(i,sa[rank[i]-1],max(height[i-1],1));
 72 end;
 73
 74 function solve(x,y:longint):longint;
 75 var i,tot:longint;
 76 begin
 77     x:=rank[x];i:=x;tot:=0;
 78     while (i>=1)and(height[sa[i]]>=y) do
 79     begin
 80         if (pos[sa[i-1]]<>0)and(vis[pos[sa[i-1]]]<>x) then
 81         begin
 82             inc(tot);vis[pos[sa[i-1]]]:=x;inc(ans[pos[sa[i-1]]]);
 83         end;
 84         dec(i);
 85     end;
 86     i:=x+1;
 87     while (i<n)and(height[sa[i]]>=y) do
 88     begin
 89         if (pos[sa[i]]<>0)and(vis[pos[sa[i]]]<>x) then
 90         begin
 91             inc(tot);vis[pos[sa[i]]]:=x;inc(ans[pos[sa[i]]]);
 92         end;
 93         inc(i);
 94     end;
 95     exit(tot);
 96 end;
 97
 98 begin
 99     readln(tota,totb);cnt:=0;n:=-1;
100     for i:=1 to tota do
101     begin
102         read(x);for j:=1 to x do begin inc(n);read(a[n]);inc(a[n],INF);pos[n]:=i;end;
103         inc(cnt);inc(n);a[n]:=cnt;
104         read(x);for j:=1 to x do begin inc(n);read(a[n]);inc(a[n],INF);pos[n]:=i;end;
105         inc(cnt);inc(n);a[n]:=cnt;
106     end;
107     for i:=1 to totb do
108     begin
109         ter[i]:=n+1;
110         read(x);for j:=1 to x do begin inc(n);read(a[n]);inc(a[n],INF);end;
111         len[i]:=x;
112         inc(cnt);inc(n);a[n]:=cnt;
113     end;
114     fillchar(vis,sizeof(vis),255);
115     inc(n);
116     suffix_array;
117
118     calc_height;
119     fillchar(ans,sizeof(ans),0);
120     for i:=1 to totb do writeln(solve(ter[i],len[i]));
121     for i:=1 to tota-1 do write(ans[i],‘ ‘);writeln(ans[tota]);
122 end.
时间: 2024-10-19 04:29:33

[BZOJ2754] [SCOI2012]喵星球上的点名解题报告|后缀数组的相关文章

bzoj2754 [SCOI2012]喵星球上的点名 (后缀数组+树状数组)

2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MB Submit: 2745 Solved: 1190 [Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么

BZOJ_2754__[SCOI2012]_喵星球上的点名_(暴力+后缀数组)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2754 给出n个姓名串和m个点名串.求每个点名串在多少人的姓名中出现过(在名中出现或在姓中出现,不能跨越),以及最后每个人被点到多少次. 分析 这种解法是用后缀数组优化一下暴力,(优化了吗?)复杂度并不能保证,然而能A... 我们先把所有名,姓,点名串都接在一个串里面. 然后匹配问题就转化成了后缀的最长公共前缀问题. 但是由于我们讨论问题的对象是名,姓,以及点名串,所以每个部分我们用不同的分隔

BZOJ2754 SCOI2012喵星球上的点名

绝世好题. 正当我犹豫不决时,hzwer说:“MAP!!!” 没错这题大大的暴力,生猛的stl,贼基尔爽,,???,, 由于我们求点名在名字中的子串个数,所以将点名建AC自动机,记录节点属于哪次点名,每次带着这位同学的所有名字去里面扫,注意判重 复杂度20000*100000以及玄学的stl复杂度. By:大奕哥 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 int ans1[N],ans2[N

bzoj2754 [SCOI2012]喵星球上的点名

题目链接 AC自动机 由于输入的是恶心的数字,用了map强行带log…… 由于不清楚长度,用了vector强行增加时间…… 由于要判重,用了数组存下强行加常数…… 慢惨了 1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cstdio> 6 #include<string> 7 #include&l

BZOJ 2754([SCOI2012]喵星球上的点名-后缀数组统计序列集合中子序列出现次数)

2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 805  Solved: 380 [Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,

BZOJ 2754: [SCOI2012]喵星球上的点名 [后缀数组+暴力]

2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1906  Solved: 839[Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那

BZOJ 2754: [SCOI2012]喵星球上的点名

2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1926  Solved: 850[Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么这

bzoj 2754 [SCOI2012]喵星球上的点名(后缀数组)

2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1359  Solved: 618[Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那

P2336 [SCOI2012]喵星球上的点名(后缀自动机+莫队)

P2336 [SCOI2012]喵星球上的点名 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<map> #define rint register int using namespace std; int read(){ char c=getchar();int x=0; while(