哈希也是有技巧的。不然很容易错。
匹配串范围是1e6的,所以普通hash错误概率也是很大的
所以就要利用匹配的特性(长度与匹配串一一对应)来hash,这样错误概率会小,相当于hash挂链吧。
一开始写的每个前缀hash存位置。这样一个hash里就有1e6个值。
码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<map>
#include<cstring>
#define P 2147483647
#define ll long long
#define D(x) cout<<x<<" ";
using namespace std;
#define N 2000005
#define ll long long
vector<int>v[N];
ll qian[N],hou[N];
int sz[N],fu[N],f[N],g[N],vf[N],vg[N],i,j,n,m,ans,tot,rt,now,T,a,b;
ll ci[N],lin;
char ch[N],S[N];
bool vis[N];
void dfs(int o,int fa)
{
int i,nd;
sz[o]=1;fu[o]=fa;
for(i=0;i<v[o].size();i++)
{
nd=v[o][i];
if(nd==fa||vis[nd])continue;dfs(nd,o);
sz[o]+=sz[nd];
}
}
void zzx(int o,int qsz)
{
int szcnt=0,i,nd,maxx=qsz;
for(i=0;i<v[o].size();i++)
if(vis[v[o][i]]==0&&fu[o]!=v[o][i])szcnt+=sz[v[o][i]],maxx=max(maxx,sz[v[o][i]]);
if(maxx<=tot/2)rt=o;
for(i=0;i<v[o].size();i++)
{
nd=v[o][i];
if(nd==fu[o]||vis[nd])continue;
zzx(nd,qsz+1+szcnt-sz[nd]);
}
}
void Dfs(int o,int fa,ll lin,int dis)
{
int i,nd;
if(qian[dis]==lin&&vg[m-dis%m-1]==now) //统计答案
ans+=g[m-dis%m-1];
if(hou[dis]==lin&&vf[m-dis%m-1]==now) //统计答案
ans+=f[m-dis%m-1];
for(i=0;i<v[o].size();i++)
{
nd=v[o][i];
if(nd==fa||vis[nd])continue;
Dfs(nd,o,(lin+(1ll*(ch[nd]-'A'+1)*ci[dis+1])%P)%P,dis+1);
}
}
void dfS(int o,int fa,ll lin,int dis)
{
int i,nd;
if(qian[dis]==lin) //统计答案
{
if(vf[dis%m]!=now)vf[dis%m]=now,f[dis%m]=0;
f[dis%m]++;
}
if(hou[dis]==lin) //统计答案
{
if(vg[dis%m]!=now)vg[dis%m]=now,g[dis%m]=0;
g[dis%m]++;
}
for(i=0;i<v[o].size();i++)
{
nd=v[o][i];
if(nd==fa||vis[nd])continue;
dfS(nd,o,(lin+(1ll*(ch[nd]-'A'+1)*ci[dis+1])%P)%P,dis+1);
}
}
void solve(int o)
{
now=o;
int i,nd,hx=ch[o]-'A'+1;
if(qian[0]==hx)vf[0]=o,f[0]=1;
if(hou[0]==hx)vg[0]=o,g[0]=1;
if(vf[0]==o&&vf[0]==vg[m-1])
ans+=g[m-1];
for(i=0;i<v[o].size();i++)
{
nd=v[o][i];
if(vis[nd])continue;
Dfs(nd,o,(hx+(ch[nd]-'A'+1)*ci[1])%P,1);
dfS(nd,o,(hx+(ch[nd]-'A'+1)*ci[1])%P,1);
}
}
void work(int o)
{
vis[o]=1;
solve(o);
int i,nd;
for(i=0;i<v[o].size();i++)
{
nd=v[o][i];
if(vis[nd]||sz[nd]<m)continue;
tot=sz[nd]; dfs(nd,o);zzx(nd,0); dfs(rt,0);
work(rt);
}
}
int main()
{
ci[0]=1;
for(i=1;i<=100000;i++)ci[i]=(ci[i-1]*27)%P;
scanf("%d",&T);
while(T--)
{ans=0;
memset(vf,0,sizeof(vf));
memset(vg,0,sizeof(vg));
memset(vis,0,sizeof(vis));
for(i=1;i<=100000;i++)
v[i].clear();
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%c",&ch[i]);
while(ch[i]<'A'||ch[i]>'Z')scanf("%c",&ch[i]);
}
for(i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
v[a].push_back(b);
v[b].push_back(a);
}
for(i=1;i<=m;i++)
{
scanf("%c",&S[i]);while(S[i]<'A'||S[i]>'Z')scanf("%c",&S[i]);
}
lin=0;
for(i=0;i<=n;i++)
{
lin=(lin*27+1ll*(S[(i%m)+1]-'A'+1))%P;
qian[i]=lin;
}
lin=0;
for(i=0;i<=n;i++)
{
lin=(lin*27+1ll*(S[(m-i%m-1)+1]-'A'+1))%P;
hou[i]=lin;
}
dfs(1,0);
tot=n;
zzx(1,0); dfs(rt,0);
work(rt); printf("%d\n",ans);
}
}