bzoj4516: [Sdoi2016]生成魔咒

Posted OldJang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4516: [Sdoi2016]生成魔咒相关的知识,希望对你有一定的参考价值。

4516: [Sdoi2016]生成魔咒

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 710  Solved: 393
[Submit][Status][Discuss]

Description

魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示。例如可以将魔咒字符 1、2 拼凑起来形成一个魔咒串 [1,2]。
一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒。
例如 S=[1,2,1] 时,它的生成魔咒有 [1]、[2]、[1,2]、[2,1]、[1,2,1] 五种。S=[1,1,1] 时,它的生成魔咒有 [1]、
[1,1]、[1,1,1] 三种。最初 S 为空串。共进行 n 次操作,每次操作是在 S 的结尾加入一个魔咒字符。每次操作后都
需要求出,当前的魔咒串 S 共有多少种生成魔咒。
 

Input

 

第一行一个整数 n。
第二行 n 个数,第 i 个数表示第 i 次操作加入的魔咒字符。
1≤n≤100000。,用来表示魔咒字符的数字 x 满足 1≤x≤10^9

Output

输出 n 行,每行一个数。第 i 行的数表示第 i 次操作后 S 的生成魔咒数量

 

Sample Input

7
1 2 3 3 3 1 2

Sample Output

1
3
6
9
12
17
22
 
题解
这题就是求有多少个不同子串……不过首先我不会SAM,其次pascal没有set
于是我就用后缀数组+fhqtreap强行写了一发……首先把串反过来跑后缀数组求出h数组,之后每次插入一个字符就是相当于多了一个新后缀,查一下这个后缀在当前已加入的后缀里rank的前驱后继,然后求一下最长公共前缀,后缀长度减去最长公共前缀就是加入一个字符所增加的子串个数
1A赞啊>_<
  1 program j01;
  2 const maxn=100086;
  3 type xx=record w,id:longint; end;
  4 var op:array[0..maxn]of xx;
  5     sa,tsa,rank,trank,sum,s,mn,h:array[0..maxn]of longint;
  6     st:array[0..20,0..maxn]of longint;
  7     len,tot,i,l,r,root,k1,k2:longint;
  8     t:array[0..maxn]of record f,w,l,r:longint; end;
  9     ans:array[0..maxn]of int64;
 10     now,tmp:int64;
 11 
 12 procedure swap(var a,b:longint);
 13 var c:longint;
 14 begin
 15   c:=a;a:=b;b:=c;
 16 end;
 17 
 18 function max(a,b:longint):longint;
 19 begin
 20   if a>b then exit(a) else exit(b);
 21 end;
 22 
 23 function min(a,b:longint):longint;
 24 begin
 25   if a<b then exit(a) else exit(b);
 26 end;
 27 
 28 procedure qsort(l,r:longint);
 29 var i,j,x:longint;y:xx;
 30 begin
 31   i:=l;j:=r;x:=op[(i+j)div 2].w;
 32   repeat
 33     while op[i].w<x do inc(i);
 34     while x<op[j].w do dec(j);
 35     if i<=j then
 36     begin
 37       y:=op[i];op[i]:=op[j];op[j]:=y;
 38       inc(i);dec(j);
 39     end;
 40   until i>j;
 41   if i<r then qsort(i,r);
 42   if l<j then qsort(l,j);
 43 end;
 44 
 45 procedure disc;
 46 var i:longint;
 47 begin
 48   qsort(1,len);
 49   tot:=1;s[op[1].id]:=1;
 50   for i:=2 to len do
 51   begin
 52     if(op[i].w<>op[i-1].w)then inc(tot);
 53     s[op[i].id]:=tot
 54   end;
 55 end;
 56 
 57 procedure getsa;
 58 var i,j,m,p:longint;
 59 begin
 60   fillchar(sum,sizeof(sum),0);m:=tot;
 61   for i:=1 to len do rank[i]:=s[i];
 62   for i:=1 to len do inc(sum[rank[i]]);
 63   for i:=1 to m do inc(sum[i],sum[i-1]);
 64   for i:=len downto 1 do
 65   begin
 66     sa[sum[rank[i]]]:=i;dec(sum[rank[i]]);
 67   end;
 68   m:=1;trank[sa[1]]:=1;
 69   for i:=2 to len do
 70   begin
 71     if(rank[sa[i]]<>rank[sa[i-1]])then inc(m);
 72     trank[sa[i]]:=m;
 73   end;
 74   j:=1;rank:=trank;
 75   while m<len do
 76   begin
 77     fillchar(sum,sizeof(sum),0);p:=0;
 78     for i:=len-j+1 to len do
 79     begin
 80       inc(p);tsa[p]:=i;
 81     end;
 82     for i:=1 to len do
 83       if sa[i]>j then
 84       begin
 85         inc(p);tsa[p]:=sa[i]-j;
 86       end;
 87     for i:=1 to len do inc(sum[rank[i]]);
 88     for i:=1 to m do inc(sum[i],sum[i-1]);
 89     for i:=len downto 1 do
 90     begin
 91       sa[sum[rank[tsa[i]]]]:=tsa[i];dec(sum[rank[tsa[i]]]);
 92     end;
 93     m:=1;trank[sa[1]]:=1;
 94     for i:=2 to len do
 95     begin
 96       if(rank[sa[i]]<>rank[sa[i-1]])or(rank[sa[i]+j]<>rank[sa[i-1]+j])then
 97         inc(m);
 98       trank[sa[i]]:=m;
 99     end;
100     j:=j*2;rank:=trank;
101   end;
102 end;
103 
104 procedure geth;
105 var i,j,k:longint;
106 begin
107   k:=0;
108   for i:=1 to len do
109   begin
110     if rank[i]=1 then
111     begin
112       h[rank[i]]:=0;continue;
113     end;
114     j:=sa[rank[i]-1];
115     while(s[i+k]=s[j+k])do inc(k);
116     h[rank[i]]:=k;
117     if k>0 then dec(k);
118   end;
119 end;
120 
121 procedure getst;
122 var i,j,a,b:longint;
123 begin
124   mn[0]:=-1;
125   for i:=1 to len do
126     if i and(i-1)=0 then mn[i]:=mn[i-1]+1 else mn[i]:=mn[i-1];
127   for i:=1 to len do st[0,i]:=h[i];
128   for i:=1 to mn[len] do
129     for j:=1 to len+1-(1 shl i) do
130       st[i,j]:=min(st[i-1,j],st[i-1,j+(1 shl(i-1))]);
131 end;
132 
133 function ask(a,b:longint):longint;
134 var d:longint;
135 begin
136   if a>b then swap(a,b);
137   d:=mn[b-a+1];
138   exit(min(st[d,a],st[d,b-(1 shl d)+1]));
139 end;
140 
141 procedure split(i,x:longint;var k1,k2:longint);
142 begin
143   if i=0 then
144   begin
145     k1:=0;k2:=0;exit;
146   end;
147   if t[i].w<x then
148   begin
149     k1:=i;split(t[i].r,x,t[i].r,k2);
150   end else
151   begin
152     k2:=i;split(t[i].l,x,k1,t[i].l);
153   end;
154 end;
155 
156 function merge(x,y:longint):longint;
157 begin
158   if(x=0)and(y=0) then exit(x+y);
159   if t[x].f>t[y].f then
160   begin
161     t[x].r:=merge(t[x].r,y);exit(x);
162   end else
163   begin
164     t[y].l:=merge(x,t[y].l);exit(y);
165   end;
166 end;
167 
168 begin
169   randomize;
170   readln(len);
171   for i:=1 to len do
172   begin
173     read(s[i]);op[i].id:=i;op[i].w:=s[i];
174   end;
175   disc;for i:=1 to len div 2 do swap(s[i],s[len-i+1]);
176   getsa;geth;
177   getst;
178   root:=0;
179   for i:=len downto 1 do
180   begin
181     split(root,rank[i],k1,k2);
182     l:=k1;while t[l].r>0 do l:=t[l].r;
183     r:=k2;while t[r].l>0 do r:=t[r].l;
184     t[i].f:=random(maxlongint);t[i].w:=rank[i];
185     root:=merge(merge(k1,i),k2);
186     tmp:=0;
187     if l>0 then tmp:=max(tmp,ask(rank[l]+1,rank[i]));
188     if r>0 then tmp:=max(tmp,ask(rank[i]+1,rank[r]));
189     now:=now+len-i+1-tmp;
190     writeln(now);
191   end;
192 end.

 

以上是关于bzoj4516: [Sdoi2016]生成魔咒的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 4516: [Sdoi2016]生成魔咒

bzoj4516 [Sdoi2016]生成魔咒

BZOJ4516SDOI2016生成魔咒 [SAM]

BZOJ - 4516: [Sdoi2016]生成魔咒

BZOJ 4516: [Sdoi2016]生成魔咒

bzoj4516: [Sdoi2016]生成魔咒(SAM)