1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| #include<bits/stdc++.h> using namespace std; #pragma GCC optimize(2) #define reg register #define Mod1(x) ((x>=P)&&(x-=P)) #define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i) #define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i) char IO; int rd(){ int s=0; while(!isdigit(IO=getchar())); do s=(s<<1)+(s<<3)+(IO^'0'); while(isdigit(IO=getchar())); return s; }
const int N=5e4+10,P=10007;
int n,m,len; char str[N],t[N]; struct Node{ int a[31][31]; void clear(){ memset(a,0,sizeof a); } void Init(int u) { clear(); rep(i,1,len) if(t[i]==str[u]) a[i][i]=1; } Node operator + (const Node &x) const { Node res; res.clear(); rep(i,1,len) for(int j=i;j<len && a[i][j];++j) for(int k=j+1;k<=len && x.a[j+1][k];++k) res.a[i][k]=(res.a[i][k]+a[i][j]*x.a[j+1][k])%P; rep(i,1,len) rep(j,i,len) { res.a[i][j]+=a[i][j],Mod1(res.a[i][j]); res.a[i][j]+=x.a[i][j],Mod1(res.a[i][j]); } return res; } } s[N];
struct Edge{ int to,nxt; }e[N<<1]; int head[N],ecnt; void AddEdge(int u,int v) { e[++ecnt]=(Edge){v,head[u]}; head[u]=ecnt; } #define erep(u,i) for(int i=head[u];i;i=e[i].nxt)
int QX[N],QY[N],QL[N]; int dep[N],id[N],fa[N][18]; void pre_dfs(int u,int f) { dep[u]=dep[fa[u][0]=f]+1; rep(i,1,17) fa[u][i]=fa[fa[u][i-1]][i-1]; erep(u,i) { int v=e[i].to; if(v==f) continue; pre_dfs(v,u); } } int LCA(int x,int y) { if(dep[x]<dep[y]) swap(x,y); for(int i=0,del=dep[x]-dep[y];(1<<i)<=del;++i) if(del&(1<<i)) x=fa[x][i]; if(x==y) return x; drep(i,17,0) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; }
int F[N],ans[N][31],Ans[N]; int Find(int x,int k=0) { if(F[x]==x) return x; int f=F[x]; F[x]=Find(f,k); if(F[f]!=f){ if(!k) s[x]=s[x]+s[f]; else s[x]=s[f]+s[x]; } return F[x]; }
int main(){ rep(kase,1,rd()) { n=rd(),m=rd(); rep(i,1,n) head[i]=ecnt=0; rep(i,2,n) { int u=rd(),v=rd(); AddEdge(u,v),AddEdge(v,u); } scanf("%s%s",str+1,t+1),len=strlen(t+1); pre_dfs(1,0); rep(i,1,m) id[i]=i,QX[i]=rd(),QY[i]=rd(),QL[i]=LCA(QX[i],QY[i]); sort(id+1,id+m+1,[&](int x,int y){ return dep[QL[x]]>dep[QL[y]]; });
rep(i,1,n) F[i]=i,s[i].clear(); rep(k,1,m){ int i=id[k],x=QX[i]; while(1){ int y=Find(x); if(y==QL[i]) break; F[y]=fa[y][0],s[y].Init(y); } ans[i][0]=1; rep(j,1,len) ans[i][j]=s[x].a[1][j]; drep(j,len,1) if(str[QL[i]]==t[j]) ans[i][j]+=ans[i][j-1],Mod1(ans[i][j]); }
rep(i,1,n) F[i]=i,s[i].clear(); rep(k,1,m){ int i=id[k],x=QY[i]; Ans[i]=0; while(1){ int y=Find(x,1); if(y==QL[i]) break; F[y]=fa[y][0],s[y].Init(y); } rep(j,0,len-1) Ans[i]=(Ans[i]+ans[i][j]*s[x].a[j+1][len])%P; Ans[i]=(Ans[i]+ans[i][len])%P; } rep(i,1,m) printf("%d\n",Ans[i]); } }
|