BZOJ4477 JSOI2015字符串树(可持久化trie)
树上建可持久化trie即可,有点过于裸了。darkbzoj过了然而在bzoj一直wa,不知道哪有锅。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 100010 int n,m,p[N],fa[N][19],deep[N],root[N],t,cnt; struct data{int to,nxt;char s[11]; }edge[N<<1]; struct data2{int x,ch[26]; }tree[N*11]; void addedge(int x,int y,char *s){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;memcpy(edge[t].s,s,sizeof(s));} void ins(int &k,int p,char *s,int n) { tree[++cnt]=tree[k],k=cnt;tree[k].x++; if (p==n) return; ins(tree[k].ch[s[p+1]-'a'],p+1,s,n); } int query(int k,int p,char *s,int n) { if (!k) return 0; if (p==n) return tree[k].x; return query(tree[k].ch[s[p+1]-'a'],p+1,s,n); } void dfs(int k) { for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k][0]) { fa[edge[i].to][0]=k; deep[edge[i].to]=deep[k]+1; root[edge[i].to]=root[k]; ins(root[edge[i].to],0,edge[i].s,strlen(edge[i].s+1)); dfs(edge[i].to); } } int lca(int x,int y) { if (deep[x]<deep[y]) swap(x,y); for (int j=18;~j;j--) if (deep[fa[x][j]]>=deep[y]) x=fa[x][j]; if (x==y) return x; for (int j=18;~j;j--) if (fa[x][j]!=fa[y][j]) x=fa[x][j],y=fa[y][j]; return fa[x][0]; } int main() { #ifndef ONLINE_JUDGE freopen("bzoj4477.in","r",stdin); freopen("bzoj4477.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(); for (int i=1;i<n;i++) { int x=read(),y=read(); char s[11];scanf("%s",s+1); addedge(x,y,s); } dfs(1); fa[1][0]=1; for (int j=1;j<19;j++) for (int i=1;i<=n;i++) fa[i][j]=fa[fa[i][j-1]][j-1]; m=read(); while (m--) { int x=read(),y=read(); char s[11];scanf("%s",s+1); printf("%d\n",query(root[x],0,s,strlen(s+1))+query(root[y],0,s,strlen(s+1))-(query(root[lca(x,y)],0,s,strlen(s+1))<<1)); } return 0; }