题目大意:
题解:
这题其实认真读题可以发现:
对于任意匹配的2个字符串x,y,无非就3种情况:
①x,y都不含 * ,这里可以直接用hash判断所有的这种情况的x是否相等,因为不含*,所以x必定等于y,否则必定不匹配
②x,y都含 * ,此时我们发现当x的第一个 * 的前缀,设为xy1,与y的第一个 * 的前缀,设为xy2
必定短的一个是长的一个的前缀,否则无法匹配
对于他们的后缀,设yx1为x中[最后一个 * 位置,x长度],yx2同理
则必定短的一个是长的一个的后缀,否则也无法匹配 这一判断可以用枚举实现,当然排序可以更优,尽管我没加
注意,对于一种情况:
1qaz2wsx3edc4rfv5tgb6yhn7uj*
*qaz2wsx4edc4rfv5tgb6yhn7ujm
这种情况是无法匹配的,而我一开始以为能够匹配,ε=(´ο`*)))唉
③x,y任意一个中含 * ,另外一个不含 *
假设含 * 的是x,那么我们可以将x的 * 全部去掉,
然后分开成一个个子串x1,x2,x3……
我们将x1,x2,x3……去跟y匹配,只要y满足x1,x2,x3能够依次出现即能够匹配,否则不匹配
这里能够用Kmp实现,不过要注意:
y并不用去枚举,因为对于任意一组卡组,它只可能存在一组y,在读入的时候记录即可,
而如果全部都带 * 则不存在这样一个不含 * 的 y,此时跳到②去实现
代码:
const
modn=10000007;
var
a:array [0..1000001] of ansistring;
b,d:array [0..1000001] of boolean;
next:array [0..20000001] of longint;
c:array [0..1000001,1..2] of longint;
maxl,minr,i,j,k,l,ii,jj,kk,n,t,m:longint;
op,s:ansistring;
check:boolean;
function insert():longint;
var
j:longint;
begin
insert:=0;
for j:=1 to length(a[i]) do
begin
if (c[i,1]=0) and (a[i][j]='*') then c[i,1]:=j;
if a[i][j]='*' then c[i,2]:=j;
insert:=(insert+ord(a[i][j])*j) mod modn;
end;
end;
begin
assign(input,'hs.in'); reset(input);
assign(output,'hs.out');rewrite(output);
readln(t);
while t>=1 do
begin
k:=0;
j:=0;
l:=0;
maxl:=0;
minr:=0;
readln(n);
check:=true;
for i:=1 to n do
begin
readln(a[i]);
c[i,1]:=0;
c[i,2]:=0;
j:=insert();
b[i]:=true;
d[i]:=true;
if c[i,1]=0 then
begin
if (k<>0) and (j<>k) then check:=false;
k:=j;
b[i]:=false;
d[i]:=false;
l:=i;
end
else begin
if c[i,1]>maxl then maxl:=c[i,1];
if length(a[i])-c[i,2]>minr
then minr:=length(a[i])-c[i,2];
end;
end;
if check then
begin
for i:=1 to maxl do
if check then
begin
for j:=1 to n do
if b[j] then
if a[j][i]='*' then b[j]:=false;
for j:=1 to n do
if (b[j]) then break;
if b[j] then
for k:=1 to n do
if b[k] then
if a[j][i]<>a[k][i] then check:=false;
end;
for i:=1 to minr do
if check then
begin
for j:=1 to n do
if d[j] then
if a[j][length(a[j])-i+1]='*' then d[j]:=false;
for j:=1 to n do
if (d[j]) then break;
if d[j] then
for k:=1 to n do
if d[k] then
if a[k][length(a[k])-i+1]<>a[j][length(a[j])-i+1]
then check:=false;
end;
end;
if check then
if l<>0 then
begin
for kk:=1 to n do
if check then
if c[kk,1]<>0 then
begin
op:='';
k:=1;
if a[kk,1]='*' then delete(a[kk],1,1);
if a[kk][length(a[kk])]<>'*'
then a[kk]:=a[kk]+'*';
for i:=1 to length(a[kk]) do
if check then
if a[kk][i]='*' then
begin
next[1]:=0;
jj:=0;
for ii:=2 to length(op) do
begin
while (jj>0) and (op[jj+1]<>op[ii]) do jj:=next[jj];
if op[jj+1]=op[ii] then inc(jj);
next[ii]:=jj;
end;
jj:=0;
for j:=k to length(a[l]) do
begin
while (jj>0) and (op[jj+1]<>a[l][j]) do jj:=next[jj];
if jj+1<=length(op) then
if a[l][j]=op[jj+1] then inc(jj);
if jj=length(op) then break;
end;
if jj=length(op) then k:=j+1
else check:=false;
op:='';
end
else op:=op+a[kk][i];
end;
end;
if check then writeln('Y')
else writeln('N');
dec(t);
end;
close(input); close(output);
end.