bzoj2351 2462

时间:2024-08-17 12:34:50

我没写hash,写了一些奇怪的做法,好像被hash随便操了……

如果没有多测,那么这道题是白书上的例题

把询问矩阵当作a个模板串,建成一个ac自动机

把一开始的矩阵当作n个串放到自动机上匹配,找到a个模板串所有出现的位置

然后找到对应矩阵的左上角上计数(即如果是第i个模板串出现在第x个串的第y个位置,则g[x-i+1,y-b+1]++)

然后判断是否有能接收a个模板串的左上角即可

加了一些剪枝过了2462……

然后2351无限TLE……

要来数据发现,当a=4 b=5的那个点跑了好长时间

有什么做法可以在a非常小的时候快速出解呢?(我就是不想写hash……)

由于询问的a,b都是一定的,我们可以把a行的矩阵压成一个串,每一列压成一个二进制位即可

这样就是给定n-a+1个长度为m的串,问一个长度为b的串是否是其中一个串的子串

这……后缀自动机随便做,这个点就跑得飞快了(因为这样复杂度是O(2^a*n*m+q*a*b了)

注意一下内存……

附上猥琐的代码

 type node=record
po,next:longint;
end; var trie,po:array[..,''..''] of longint;
go:array[..,..] of longint;
w,f:array[..] of longint;
p,q:array[..] of longint;
g,v:array[..,..] of longint;
e:array[..] of node;
te,last,n,m,a,b,len,ans,i,j,t,tot,k,l:longint;
c:array[..] of ansistring;
s:ansistring;
ch:char; procedure add(x,y:longint);
begin
inc(len);
e[len].po:=y;
e[len].next:=p[x];
p[x]:=len;
end; procedure fill(x0,y0,x:longint);
var i,y,xx,yy:longint;
begin
i:=p[x];
while i<> do
begin
y:=e[i].po;
xx:=x0-y+;
yy:=y0-b+;
if xx> then
begin
if v[xx,yy]<>te then
begin
v[xx,yy]:=te;
g[xx,yy]:=;
end;
inc(g[xx,yy]);
if g[xx,yy]>ans then ans:=g[xx,yy];
if ans=a then exit;
end;
i:=e[i].next;
end;
end; procedure ac;
var j,h,r,x,y:longint;
c:char;
begin
h:=;
r:=;
for c:='' to '' do
if trie[,c]> then
begin
inc(r);
q[r]:=trie[,c];
f[trie[,c]]:=;
end; while h<=r do
begin
x:=q[h];
for c:='' to '' do
if trie[x,c]> then
begin
y:=trie[x,c];
inc(r);
q[r]:=y;
j:=f[x];
while (j>) and (trie[j,c]=) do j:=f[j];
f[y]:=trie[j,c];
end;
inc(h);
end;
end; procedure change(c:longint);
var q,p,np:longint;
begin
p:=go[last,c];
if w[p]=w[last]+ then last:=p
else begin
inc(t); np:=t;
w[np]:=w[last]+;
go[np]:=go[p];
f[np]:=f[p];
f[p]:=np;
q:=last;
while go[q,c]=p do
begin
go[q,c]:=np;
q:=f[q];
end;
last:=np;
end;
end; procedure ins(c:longint);
var np,nq,p,q:longint;
begin
p:=last;
inc(t); last:=t; np:=t;
w[np]:=w[p]+;
while (p<>) and (go[p,c]=) do
begin
go[p,c]:=np;
p:=f[p];
end;
if p= then f[np]:=
else begin
q:=go[p,c];
if w[q]=w[p]+ then f[np]:=q
else begin
inc(t); nq:=t;
w[nq]:=w[p]+;
go[nq]:=go[q];
f[nq]:=f[q];
f[q]:=nq; f[np]:=nq;
while go[p,c]=q do
begin
go[p,c]:=nq;
p:=f[p];
end;
end;
end;
end; procedure make(l,r,m:longint);
var i,j:longint;
begin
for j:= to m do
begin
p[j]:=;
for i:=l to r do
p[j]:=p[j]+g[i,j]*( shl (i-l));
end;
end; begin
readln(n,m,a,b);
if a> then
begin
for i:= to n do
readln(c[i]);
readln(te);
while te> do
begin
dec(te);
j:=;
trie[,'']:=;
trie[,'']:=;
t:=;
len:=;
for i:= to a do
begin
readln(s);
j:=;
for k:= to b do
begin
if trie[j,s[k]]= then
begin
inc(t); p[t]:=; w[t]:=k;
trie[t,'']:=; trie[t,'']:=;
trie[j,s[k]]:=t;
end;
j:=trie[j,s[k]];
end;
add(j,i);
end;
ac;
for i:= to t do
for ch:='' to '' do
begin
j:=i;
while (j>) and (trie[j,ch]=) do j:=f[j];
j:=trie[j,ch];
po[i,ch]:=j;
end; ans:=;
for i:= to n do
begin
j:=;
for k:= to m do
begin
if not((c[i][k]>='') and (c[i][k]<='')) then break;
if b-w[j]>m-k+ then break;
j:=po[j,c[i][k]];
if p[j]<> then
begin
fill(i,k,j);
if ans=a then break;
end;
end;
if (ans=a) or (n-i+ans<a) then break;
end;
writeln(ans div a);
end;
end
else begin
t:=;
for i:= to n do
begin
for j:= to m do
begin
read(ch);
g[i,j]:=ord(ch)-;
end;
readln;
end;
for i:= to n-a+ do
begin
make(i,i+a-,m);
last:=;
for j:= to m do
if go[last,p[j]]<> then change(p[j])
else ins(p[j]);
end;
readln(te);
while te> do
begin
dec(te);
for i:= to a do
begin
for j:= to b do
begin
read(ch);
g[i,j]:=ord(ch)-;
end;
readln;
end;
make(,a,b);
j:=;
ans:=;
for i:= to b do
if go[j,p[i]]= then
begin
ans:=;
break;
end
else j:=go[j,p[i]];
writeln(ans);
end;
end;
end.