zoukankan      html  css  js  c++  java
  • [SDOI2016]模式字符串

    题目

    bzoj第400题留念

    这道题如果只有前三组数据的话还是很水的呀,我们完全可以点分

    首先我们先倍长那个字符串,直到这个字符串的长度大于等于(n)

    我们把这个字符串做一遍(hash),记下每一个前缀每一个后缀的(hash)值是多少

    之后套路点分,对于当前的分治重心找出一个前缀一个后缀来拼接,由于我们倍长了原串,我们可以方便的直到当前连通块里某个点到分治重心的路径是否能形成一个前缀或一个后缀,我们开一个桶记录一下就好了

    之后就只有(bzoj)上能过了

    代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define ull unsigned int
    #pragma GCC optimize(3)
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    const int maxn=1e5+5;
    const int inf=999999999;
    struct E{int v,nxt;}e[maxn<<1];
    int head[maxn],vis[maxn],sum[maxn],mx[maxn],st[maxn],tax[maxn],cl[maxn];
    int n,num,Case,rt,Ss,top,tot,m,len;LL ans=0;
    ull ha[maxn],pw[maxn],base=233,pr[maxn],bh[maxn];
    char S[maxn],a[maxn],T[maxn];
    inline void add(int x,int y) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
    void getroot(int x,int fa) {
    	sum[x]=1;mx[x]=0;
    	for(re int i=head[x];i;i=e[i].nxt) {
    		if(vis[e[i].v]||e[i].v==fa) continue;
    		getroot(e[i].v,x);sum[x]+=sum[e[i].v];
    		mx[x]=max(mx[x],sum[e[i].v]);
    	}
    	mx[x]=max(mx[x],Ss-sum[x]);
    	if(mx[x]<mx[rt]) rt=x;
    }
    void getpre(int x,int l,ull sh,int fa) {
    	sh=sh+a[x]*pw[l];
    	if(pr[l+1]==sh) st[++top]=(l+1)%m;
    	for(re int i=head[x];i;i=e[i].nxt) {
    		if(vis[e[i].v]||e[i].v==fa) continue;
    		getpre(e[i].v,l+1,sh,x);
    	}
    }
    void getbeh(int x,int l,ull sh,int fa) {
    	sh=sh*base+a[x];
    	if(bh[l]==sh) ans+=tax[(m-l%m)%m];
    	for(re int i=head[x];i;i=e[i].nxt) {
    		if(vis[e[i].v]||e[i].v==fa) continue;
    		getbeh(e[i].v,l+1,sh,x);
    	}
    }
    void dfs(int x) {
    	vis[x]=1;tot=0;
    	if(a[x]==S[1]) tax[1]++;
    	for(re int i=head[x];i;i=e[i].nxt) {
    		if(vis[e[i].v]) continue;
    		getbeh(e[i].v,1,0,x);
    		top=0;getpre(e[i].v,1,a[x],x);
    		while(top) tax[st[top]]++,cl[++tot]=st[top--];
    	}
    	tax[1]=0;
    	while(tot) tax[cl[tot--]]=0;
    	for(re int i=head[x];i;i=e[i].nxt) {
    		if(vis[e[i].v]) continue;
    		Ss=sum[e[i].v];rt=0;getroot(e[i].v,0);dfs(rt);
    	}
    }
    inline void work() {
    	for(re int i=1;i<=len;i++) ha[i]=ha[i-1]*base+S[(i%m)?i%m:m];
    	for(re int i=1;i<=len;i++) pr[i]=ha[i];
    	for(re int i=1;i<=len;i++) bh[i]=ha[len]-ha[len-i]*pw[i];
    	Ss=n,rt=0,getroot(1,0),dfs(rt); 
    }
    int main() {
    	Case=read();mx[0]=inf;
    	pw[0]=1;for(re int i=1;i<(maxn<<1);i++) pw[i]=pw[i-1]*base;
    	while(Case--) {
    		memset(vis,0,sizeof(vis));memset(head,0,sizeof(head));
    		n=read(),m=read();num=0;scanf("%s",a+1);
    		for(re int x,y,i=1;i<n;i++) x=read(),y=read(),add(y,x),add(x,y);
    		scanf("%s",S+1);len=m;
    		while(len<n) len+=m;
    		ans=0;work();
    		for(re int i=1;i<=m;i++) T[i]=S[i];
    		for(re int i=1;i<=m;i++) S[i]=T[m-i+1];
    		for(re int i=1;i<=n;i++) vis[i]=0;
    		work();printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    python-函数(下):递归、高阶函数
    Spring Hystrix 原理与使用详解
    Jmeter 添加kafka支持
    dnspod-sr 高性能DNS 服务器软件
    Jupyter精选资源合集
    spring 跨域CORS Filter
    TensorFlow 基础准备指导
    TortoiseGit SSH-key 免用户名密码验证
    node.js、npm 升级操作详解
    Maven -DskipTests和-Dmaven.test.skip=true的区别
  • 原文地址:https://www.cnblogs.com/asuldb/p/10805409.html
Copyright © 2011-2022 走看看