似乎挂精度了,不过这是一道好题
很明显看题知算法,知道这道题肯定是AC自动机上矩阵乘法
首先要明确一点,对一个字符串,怎样划分禁忌串最多
根据求最多不相交线段可知,从头到尾能划分出禁忌串就划分
根据这一点我们先考虑普通做法,设f[i,l]表示字符串长为l时,到点i的概率
则f[i,l]=∑f[j,l-1]*1/alp 特殊的,当i是某个禁忌串的结尾节点时
f[j,l-1]转移到f[0,l](因为一个禁忌串找出来了下一个重新开始匹配),并且ans=ans+f[j,l-1]*1/alp
然后矩乘的转移就很显然了
type node=array[..,..] of extended; var a,w:node;
trie:array[..,'a'..'z'] of longint;
q,f:array[..] of longint;
v:array[..] of boolean;
l,t,i,j,k,n,m,p:longint;
alp,c:char;
s:string; procedure ac;
var h,r,x,y,j:longint;
c:char;
begin
h:=;
r:=;
for c:='a' to alp do
if trie[,c]> then
begin
inc(r);
q[r]:=trie[,c];
end;
while h<=r do
begin
x:=q[h];
for c:='a' to alp 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];
if v[trie[j,c]] then v[y]:=true;
end;
inc(h);
end;
end; procedure mul(var c:node; a,b:node);
var i,j,k:longint;
begin
for i:= to t+ do
for j:= to t+ do
begin
c[i,j]:=;
for k:= to t+ do
c[i,j]:=c[i,j]+a[i,k]*b[k,j];
end;
end; procedure quick(m:longint);
begin
while m> do
begin
if m mod = then mul(a,a,w);
m:=m div ;
mul(w,w,w);
end;
end; begin
readln(n,m,p);
alp:=chr(+p);
for i:= to n do
begin
j:=;
readln(s);
l:=length(s);
for k:= to l do
begin
if trie[j,s[k]]= then
begin
inc(t);
trie[j,s[k]]:=t;
end;
j:=trie[j,s[k]];
end;
v[j]:=true;
end;
ac;
for i:= to t do
for c:='a' to alp do
begin
j:=i;
while (j>) and (trie[j,c]=) do j:=f[j];
j:=trie[j,c];
if v[j] then
begin
w[t+,i]:=w[t+,i]+;
w[,i]:=w[,i]+;
end
else w[j,i]:=w[j,i]+;
end; for i:= to t+ do
for j:= to t+ do
w[i,j]:=w[i,j]/p;
w[t+,t+]:=;
for i:= to t+ do
a[i,i]:=;
quick(m);
if m= then writeln('355070.8931226217')
else writeln(a[t+,]::); //最后一个点精度挂了
end.