//#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
//#include<queue>
//#include<time.h>
//#include<complex>
#include<algorithm>
#include<stdlib.h>
using namespace std; int n,m,lq;
#define maxn 200011
struct Edge{int to,next; char v;}edge[maxn<<]; int first[maxn],le=;
void in(int x,int y,char v) {Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;}
void insert(int x,int y,char v) {in(x,y,v); in(y,x,v);} struct Ques{int x,y,z,id,col,ps1,ps2;}q[maxn];
bool cmp(const Ques &a,const Ques &b) {return a.col<b.col;}
int ans[maxn]; struct AC
{
int ch[maxn][],size,pos[maxn];
AC() {size=; le=; Time=;}
int idx(char c) {return c-'a';}
void insert(int who,char *s)
{
int len=strlen(s),now=;
for (int i=;i<len;i++)
{
int id=idx(s[i]);
if (!ch[now][id])
{
size++;
ch[now][id]=size;
}
now=ch[now][id];
}
pos[who]=now;
}
int fail[maxn];
int que[maxn],head,tail;
void makefail()
{
head=tail=;
for (int i=;i<;i++) if (ch[][i])
{
fail[ch[][i]]=;
que[tail++]=ch[][i];
}
while (head!=tail)
{
int now=que[head++];
for (int i=;i<;i++)
{
if (!ch[now][i]) {ch[now][i]=ch[fail[now]][i]; continue;}
que[tail++]=ch[now][i];
fail[ch[now][i]]=ch[fail[now]][i];
}
}
}
Edge edge[maxn<<]; int first[maxn],le;
void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
int ll[maxn],rr[maxn],Time;
void predfs(int x)
{
ll[x]=++Time;
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i];
predfs(e.to);
}
rr[x]=Time;
}
void predfs()
{
for (int i=;i<=size;i++) in(fail[i],i);
predfs();
}
}a1,a2;
vector<char> ss[maxn],fs[maxn];
struct SAM
{
struct Node{int ch[],pos,pre,who,Max;}a[maxn<<];
int size,last;
SAM() {a[].pre=-; size=last=; le=; Time=;}
int idx(char c) {return c-'a';}
void insert(int who,char c,int pos)
{
int id=idx(c);
if (a[last].ch[id])
{
if (a[a[last].ch[id]].Max==a[last].Max+) last=a[last].ch[id];
else
{
int z=a[last].ch[id],w=++size; a[w]=a[z]; a[w].Max=a[last].Max+; a[w].pos=pos; a[w].who=who;
a[z].pre=w;
for (int y=last;~y && a[y].ch[id]==z;y=a[y].pre) a[y].ch[id]=w;
last=w;
}
}
else
{
int x=++size; a[x].pos=pos; a[x].who=who; a[x].Max=a[last].Max+;
int y=last; last=x;
for (;~y && !a[y].ch[id];y=a[y].pre) a[y].ch[id]=x;
if (!~y) a[x].pre=;
else if (a[a[y].ch[id]].Max==a[y].Max+) a[x].pre=a[y].ch[id];
else
{
int z=a[y].ch[id],w=++size; a[w]=a[z]; a[w].pos=pos; a[w].Max=a[y].Max+; a[w].who=who;
a[z].pre=a[x].pre=w;
for (;~y && a[y].ch[id]==z;y=a[y].pre) a[y].ch[id]=w;
}
}
}
Edge edge[maxn<<]; int first[maxn<<],le;
void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
int ll[maxn],rr[maxn],Time;
void predfs(int x)
{
ll[x]=++Time;
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i];
predfs(e.to);
}
rr[x]=Time;
}
void predfs() {for (int i=;i<=size;i++) in(a[i].pre,i); predfs();}
bool go(int &x,int &son,int &pos,char c,vector<char> *s)
{
if (!son)
{
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i]; Node &now=a[e.to];
if (s[now.who][now.pos+a[x].Max]==c)
{
son=e.to;
pos=now.pos+a[x].Max+;
break;
}
}
if (!son) return ;
}
else if (s[a[son].who][pos]==c) pos++; else return ;
if (pos==a[son].pos+a[son].Max) {x=son; son=pos=;}
return ;
}
}s1,s2;
struct BIT
{
int a[maxn<<],n;
void clear(int m) {n=m;}
void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;}
int query(int x) {int ans=; for (;x;x-=x&-x) ans+=a[x]; return ans;}
}ta1,ta2,ts; int size[maxn];
int col[maxn]; bool vis[maxn];
void getsize(int x,int fa)
{
size[x]=;
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i]; if (e.to==fa || vis[e.to]) continue;
getsize(e.to,x); size[x]+=size[e.to];
}
}
int getroot(int x,int fa,int tot)
{
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i]; if (e.to==fa || vis[e.to]) continue;
if (size[e.to]*>tot) return getroot(e.to,x,tot);
}
return x;
} void paint(int x,int fa,int c)
{
col[x]=c;
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i]; if (e.to==fa || vis[e.to]) continue;
paint(e.to,x,c);
}
}
struct Eve{int to,type,next;}eve[maxn<<]; int feve[maxn],leve=;
void ineve(int x,int y,int type) {Eve &e=eve[leve]; e.to=y; e.type=type; e.next=feve[x]; feve[x]=leve++;}
void Dfs(int x,int fa,int pa1,int pa2,int ps1,bool die1,int son1,int pos1,int ps2,bool die2,int son2,int pos2)
{
ta1.add(a1.ll[pa1],); ta2.add(a2.ll[pa2],);
for (int i=feve[x];i;i=eve[i].next)
{
Eve &e=eve[i];
if (e.type==)
{
ans[q[e.to].id]+=ta2.query(a2.rr[a2.pos[q[e.to].z]])-ta2.query(a2.ll[a2.pos[q[e.to].z]]-);
q[e.to].ps1=ps1;
}
else
{
ans[q[e.to].id]+=ta1.query(a1.rr[a1.pos[q[e.to].z]])-ta1.query(a1.ll[a1.pos[q[e.to].z]]-);
q[e.to].ps2=ps2;
}
}
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i]; if (e.to==fa || vis[e.to]) continue;
int id=e.v-'a';
int nps1=ps1,npos1=pos1,nson1=son1,nps2=ps2,npos2=pos2,nson2=son2; bool nd1=die1,nd2=die2;
if (die1) nps1=ps1,nson1=,npos1=,nd1=;
else nd1=!s1.go(nps1,nson1,npos1,e.v,fs);
if (die2) nps2=ps2,nson2=,npos2=,nd2=;
else nd2=!s2.go(nps2,nson2,npos2,e.v,ss);
Dfs(e.to,x,a1.ch[pa1][id],a2.ch[pa2][id],nps1,nd1,nson1,npos1,nps2,nd2,nson2,npos2);
}
ta1.add(a1.ll[pa1],-); ta2.add(a2.ll[pa2],-);
} void cd(int x,int ql,int qr)
{
vis[x]=; col[x]=;
if (ql>qr) return;
bool flag=; int tot=;
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i]; if (vis[e.to]) continue;
paint(e.to,,++tot);
}
for (int i=ql;i<=qr;i++)
{
if (col[q[i].x]==col[q[i].y]) q[i].col=col[q[i].x];
else flag=,q[i].col=;
}
sort(q+ql,q+qr+,cmp);
int j;
for (j=ql;j<=qr && q[j].col==;j++)
{
ineve(q[j].x,j,);
ineve(q[j].y,j,);
}
if (flag) Dfs(x,,,,,,,,,,,);
for (int k=ql;k<j;k++) feve[q[k].x]=feve[q[k].y]=; leve=;
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i]; if (vis[e.to]) continue;
int tj=j; while (j<=qr && q[j].col==col[e.to]) j++;
getsize(e.to,); cd(getroot(e.to,,size[e.to]),tj,j-);
}
} struct Bre{int tx,ty,tz,type,isq;}bre[maxn],ff[maxn<<]; int lbre=,lff=;
void inbre(int x,int y,int t) {bre[++lbre]=(Bre){x,y,,t};} char s[maxn]; int br[maxn];
bool cmpff(const Bre &a,const Bre &b) {return a.type<b.type || (a.type==b.type && a.tx<b.tx)
|| (a.type==b.type && a.tx==b.tx && a.isq<b.isq);}
int main()
{
scanf("%d%d%d",&n,&m,&lq);
char c;
for (int i=,x,y;i<n;i++)
{
scanf("%d%d",&x,&y); while ((c=getchar())<'a' || c>'z');
insert(x,y,c);
}
for (int i=;i<=m;i++)
{
s1.last=s2.last=;
scanf("%s",s); int len=strlen(s);
ss[i].push_back('$'); for (int j=;j<len;j++) ss[i].push_back(s[j]);
a1.insert(i,s); for (int j=;j<len;j++) s1.insert(i,s[j],len-j),br[j]=s1.last;
for (int j=,to=len>>;j<to;j++) s[j]^=s[len-j-]^=s[j]^=s[len-j-];
fs[i].push_back('$'); for (int j=;j<len;j++) fs[i].push_back(s[j]);
a2.insert(i,s); for (int j=;j<len-;j++) s2.insert(i,s[j],len-j),inbre(br[len-j-],s2.last,i); s2.insert(i,s[len-],);
}
for (int i=;i<=lq;i++) scanf("%d%d%d",&q[i].x,&q[i].y,&q[q[i].id=i].z); ta1.clear(a1.size+); ta2.clear(a2.size+);
a1.makefail(); a2.makefail();
a1.predfs(); a2.predfs(); s1.predfs(); s2.predfs();
getsize(,); cd(getroot(,,size[]),,lq); for (int i=;i<=lbre;i++)
{
ff[++lff]=(Bre){s1.ll[bre[i].tx],bre[i].ty,,bre[i].type,};
ff[++lff]=(Bre){s1.rr[bre[i].tx]+,bre[i].ty,-,bre[i].type,};
}
for (int i=;i<=lq;i++) ff[++lff]=(Bre){s1.ll[q[i].ps1],s2.ll[q[i].ps2],q[i].id,q[i].z,};
sort(ff+,ff++lff,cmpff);
ts.clear(s2.size+);
for (int k=;k<=lff;k++)
{
if (ff[k].isq==) ts.add(s2.ll[ff[k].ty],ff[k].tz),ts.add(s2.rr[ff[k].ty]+,-ff[k].tz);
else ans[ff[k].tz]+=ts.query(ff[k].ty);
} for (int i=;i<=lq;i++) printf("%d\n",ans[i]);
return ;
}

Codeforces917E的更多相关文章

随机推荐

  1. Android检测WIFI连接、提示框延时消失

    Android检测系统WIFI是否连接?如没有连接,显示提示框,提示进行设置,当点击设置进入系统WIFI界面后1秒钟,提示框自动消失. 代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 ...

  2. Oracle Select语句

    Oracle Select语句 作者:初生不惑 Oracle基础 评论:0 条 Oracle技术QQ群:175248146 在本教程中,将学习如何使用Oracle SELECT语句从单个表中查询数据. ...

  3. 大数据笔记(七)——Mapreduce程序的开发

    一.分析Mapreduce程序开发的流程 1.图示过程 输入:HDFS文件 /input/data.txt Mapper阶段:  K1:数据偏移量(以单词记)V1:行数据 K2:单词  V2:记一次数 ...

  4. SpringBoot:配置文件及自动配置原理

    西部开源-秦疆老师:基于SpringBoot 2.1.6 的博客教程 秦老师交流Q群号: 664386224 未授权禁止转载!编辑不易 , 转发请注明出处!防君子不防小人,共勉! SpringBoot ...

  5. shouyexinlianjie

    http://7xj7xs.com1.z0.glb.clouddn.com/trail_1.mp4

  6. Window7系统安装Ubuntu16双系统

    在电脑上插入ubuntu系统启动盘,之前做好的u盘启动盘,重启计算机,进入BIOS设置界面,设置系统启动为u盘启动,保存后退出.之后进入ubuntu系统安装界面. 在安装界面中选择系统语言,选择安装u ...

  7. leetcode-mid-Linked list-160 Intersection of Two Linked Lists-NO

    mycode 用了反转链表,所以不符合题意 参考: 思路: 1 先让长的链表先走,然后相同长度下看是否相遇 class Solution(object): def getIntersectionNod ...

  8. LinkedTransferQueue 源码分析

    LinkedTransferQueue LinkedTransferQueue 能解决什么问题?什么时候使用 LinkedTransferQueue? 1)LinkedTransferQueue 是基 ...

  9. 阶段1 语言基础+高级_1-3-Java语言高级_09-基础加强_第2节 反射_11_反射_案例

    student定义sleep方法 用反射+配置文件 定义配置文件 src下new file.新建 加载配置文件.Properties里面有一个load方法,可以加载.properties结尾的配置文件 ...

  10. win10+jdk+mysql+tomcat+jpress环境搭建与部署

    本机搭建jpress用于接口测试的学习 目录 1.环境与工具准备 2.mysql服务端安装 3.tomcat配置 4.jpress部署 1.环境与工具准备 a.服务器为本机为win10 64位 b.j ...