BZOJ4713 迷失的字符串
分析
首先考虑只有一个串时的做法,可以进行背包dp,记\(f(i,j)\)表示从\(i\)的子树中某点出发到\(i\)能否匹配字符串的\(1 \dots j\)位且\(i\)与\(j\)匹配。同时记\(g(i,j)\)表示从\(i\)出发到\(i\)的子树某点中能否匹配字符串的\(j \dots len\)位并且\(i\)与\(j\)匹配。
显然有
g(i,j)=g(i,j)|(g(k,j+1)\&[ch=s_j]),g(i,len+1)=true
\]
(\(k\)为\(i\)的儿子,\(ch\)为当前边上的字符)
把询问串拼接在一起(中间留空以防出错),\(f\)与\(g\)的区间含义改成在当前点所属串的区间含义,在父亲处合并儿子的答案并对最终答案做出贡献。如果存在\(f(i,j)=true\)且\(g(i,j+1)=true\)那么\(j\)点所属串就可以在以\(i\)为子树的字符树中匹配。
用拓扑排序确定计算顺序避免递归爆栈,用bitset优化位运算的转移提高时空效率。最后注意bzoj太慢了,所以可以把长度为1的询问串特判掉来优化常数。
时空复杂度\(O(N \cdot ∑len / 64)\)。
代码
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x){
    T data=0;
	int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
		if(ch=='-')
			w=-1;
		ch=getchar();
	}
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;
const int MAXN=30010,MAXM=35010;
struct Edge
{
	int nx,to,w;
}E[MAXN<<1];
int head[MAXN],ecnt;
void addedge(int x,int y,int w)
{
	E[++ecnt].to=y,E[ecnt].w=w;
	E[ecnt].nx=head[x],head[x]=ecnt;
}
bool exist[27]; // character exist
int s[MAXM],t[MAXM]; // string starting and ending point
char st[MAXM]; // buffer
int ch[MAXM],bl[MAXM]; // new combined string,owner of position
bool final[MAXM]; // final answer,sorted by query rank
queue <int> Q;
void dfs(int x,int fa) // topu sort
{
	for(int i=head[x];i;i=E[i].nx)
		if(E[i].to!=fa)
			dfs(E[i].to,x);
	Q.push(x);
}
bool vis[MAXN]; // avoid accessing father
bitset<MAXM> pre,suf,f[MAXN],g[MAXN],hav[27],ans,nowpre,nowsuf;
void bfs()
{
	while(!Q.empty())
	{
		int x=Q.front();
		Q.pop();
		vis[x]=true;
		f[x]=pre,g[x]=suf;
		for(int i=head[x];i;i=E[i].nx)
		{
			int y=E[i].to,w=E[i].w;
			if(!vis[y]) continue;
			nowpre=(f[y]<<1)&hav[w];
			nowsuf=(g[y]>>1)&hav[w];
			ans=ans|(f[x]&(nowsuf>>1))|(nowpre&(g[x]>>1)); // 避免在同一条链上合并答案
			f[x]=f[x]|nowpre,g[x]=g[x]|nowsuf;
		}
	}
}
int main()
{
  freopen("4713.in","r",stdin);
  freopen("4713.out","w",stdout);
	int n;
	read(n);
	for(int i=1;i<n;++i)
	{
		int x,y;
		char w[2];
		read(x);read(y);
		scanf("%s",w);
		w[0]-='a'-1;
		addedge(x,y,w[0]);
		addedge(y,x,w[0]);
		exist[int(w[0])]=true;
	}
	int m;
	read(m);
	int sum=0;
	for(int i=1;i<=m;++i)
	{
		s[i]=sum; // 两两字符串之间留空以防错。字符串前一位置留空
		scanf("%s",st+1);
		int l=strlen(st+1);
		if(l==1)
		{
			if(exist[st[1]-'a'+1])
				final[i]=true;
			continue;
		}
		for(int j=1;j<=l;++j)
			ch[sum+j]=st[j]-'a'+1;
		t[i]=sum+l+1;
		for(int j=s[i];j<t[i];++j)
			bl[j]=i;
		sum=sum+l+1;
	}
	for(int i=1;i<=m;++i)
	{ // 给f,g初始化
		pre.set(s[i]);
		suf.set(t[i]);
	}
	for(int i=0;i<=sum;++i)
		hav[ch[i]].set(i); // f,g转移用
	dfs(1,0);
	bfs();
	for(int i=0;i<=sum;++i)
		if(ans[i])
			final[bl[i]]=true;
	for(int i=1;i<=m;++i)
		if(final[i])
			puts("YES");
		else
			puts("NO");
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}
												
											BZOJ4713 迷失的字符串的更多相关文章
- BZOJ4713 迷失的字符串 解题报告
		
BZOJ4713 题目大意:有 \(n\) 个点 \(n-1\) 条边,每条边有一个字符.给你 \(m\) 个字符串 \(s_i\),问每个字符串是否可以通过树上的一条简单路径表示. \(n,m\le ...
 - web config数据库连接字符串加密
		
ASP.NET web.config中,数据库连接字符串的加密与解密 ASP.NET web.config中,数据库连接字符串的加密与解密. 开始--->运行,输入cmd,接着输入以下内容 加密 ...
 - 【CTF REVERSE】ctf02-查找字符串
		
1.前言 公司大拿给写的一个CTF逆向程序,提升我们组内人员的水平. 基于对话框MFC框架开发,使用EDIT控制特性隐藏Flag,可借助spy4win之类窗体工具找出Flag. 程序加UPX壳,已对壳 ...
 - ADO.NET:连接数据字符串
		
ylbtech-ADO.NET:ADO.NET-Oracle|SQLServer|MySql|Access|Excel-dddd ADO.NET:连接数据字符串 1.A,SqlServer返回顶部 1 ...
 - YTU 2802: 判断字符串是否为回文
		
2802: 判断字符串是否为回文 时间限制: 1 Sec 内存限制: 128 MB 提交: 348 解决: 246 题目描述 编写程序,判断输入的一个字符串是否为回文.若是则输出"Yes ...
 - YTU 2420: C语言习题 不等长字符串排序
		
2420: C语言习题 不等长字符串排序 时间限制: 1 Sec 内存限制: 128 MB 提交: 460 解决: 239 题目描述 在主函数中输入n(n<=10)个不等长的字符串.用另一函 ...
 - YTU 2419: C语言习题 等长字符串排序
		
2419: C语言习题 等长字符串排序 时间限制: 1 Sec 内存限制: 128 MB 提交: 650 解决: 249 题目描述 在主函数中输入n(n<=10)个等长的字符串.用另一函数对 ...
 - YTU 2424: C语言习题 字符串比较
		
2424: C语言习题 字符串比较 时间限制: 1 Sec 内存限制: 128 MB 提交: 1042 解决: 613 题目描述 写一函数,实现两个字符串的比较.即自己写一个strcmp函数,函数 ...
 - YTU 2417: C语言习题 字符串长度
		
2417: C语言习题 字符串长度 时间限制: 1 Sec 内存限制: 128 MB 提交: 758 解决: 548 题目描述 写一函数,求一个字符串的长度.在main函数中输入字符串,并输出其长 ...
 
随机推荐
- 雷林鹏分享:Ruby 模块(Module)
			
Ruby 模块(Module) 模块(Module)是一种把方法.类和常量组合在一起的方式.模块(Module)为您提供了两大好处. 模块提供了一个命名空间和避免名字冲突. 模块实现了 mixin 装 ...
 - 开发shellcode的艺术
			
专业术语 ShellCode:实际是一段代码(也可以是填充数据) exploit:攻击通过ShellCode等方法攻击漏洞 栈帧移位与jmp esp 一般情况下,ESP寄存器中的地址总是指向系统栈且不 ...
 - Knights of a Polygonal Table CodeForces - 994B (贪心)
			
大意:n个骑士, 每个骑士有战力p, 钱c, 每个骑士可以抢战力比他低的钱, 每个骑士最多抢k次, 对每个骑士求出最大钱数 按战力排序后, 堆维护动态前k大即可 #include <iostre ...
 - php实现频率限制
			
一.前言 公司要做呼叫中心,呼叫中心为了防止骚扰,需要限制用户拨打电话的频率,比如30s只能点击一次.这样的需求是通过redis来实现的. 二.具体实现 <?php class Resource ...
 - pytorch人脸识别——自己制作数据集
			
这是一篇面向新手的博文:因为本人也是新手,记录一下自己在做这个项目遇到的大大小小的坑. 按照下面的例子写就好了 import torch as t from torch.utils import da ...
 - @Component、@Service、@Constroller
			
@Component.@Service.@Constroller,@Repository,它们分别用于软件系统的不同层次: @Component 是一个泛化的概念,仅仅表示一个组件 (Bean) ,可 ...
 - OC 继承
			
一.基本概念 程序的世界和人类的“对象”世界在思想上是没有设么区别的,富二代继承了父母,自然就拥有了父母拥有的所有资源,子类继承了父类同样就拥有了父类所有的方法和属性(成员变量). 在这里动物是猫类和 ...
 - mybatis标签之——<trim>
			
trim标记是一个格式化的标记,主要用于拼接sql的条件语句(前缀或后缀的添加或忽略),可以完成set或者是where标记的功能. trim属性主要有以下四个 prefix:前缀覆盖并增加其内容 ...
 - POJ 1947 Rebuilding Roads 树形dp 难度:2
			
Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 9105 Accepted: 4122 ...
 - 最全的CSS浏览器兼容问题【FF与IE】
			
1. Div居中问题 div设置 margin-left, margin-right 为 auto 时已经居中,IE 不行,IE需要设定body居中,首先在父级元素定义text-algin: cent ...