给你一颗点上有字符的树,问一个给定的字符串是否是这棵树上的两点的路径。

树分治的思想就是每次找重心,重心下的子问题分解去做,然后就是合并了。合并的时候用一个总的set<pair<len,hash>> 去存从根节点往下走的长度以及对应的hash值,判的时候只需要看下是否已经存在 m-len,以及对应的前缀(或者后缀)的哈希值,然后再加进来。

两个优化的点是,1是递归解子问题的时候如果子树规模小于要给的字符串可以不用递归下去。2是存pair的时候只需要存前缀的pair以及后缀的pair,其它的都不用存。

加了这些优化之后我的程度勉强能在4000ms内通过。看来我树分治的写法还是太慢了。。

#pragma warning(disable:4996)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <ctime>
#include <map>
#include <set>
using namespace std; #define maxn 10010
#define ll long long
#define MP make_pair vector<int> G[maxn];
bool centroid[maxn];
int ssize[maxn];
char val[maxn];
char tar[maxn];
set<pair<ll, ll> > sta;
set<pair<ll, ll> >::iterator it;
int n, m; ll mod_num;
ll mod;
ll xpow[maxn];
ll pre[maxn];
ll post[maxn]; ll xorr(ll x, ll y)
{
return (x*mod_num%mod + y) % mod;
} int compute_ssize(int v, int p)
{
int c = 1;
for (int i = 0; i<G[v].size(); ++i){
int w = G[v][i];
if (w == p || centroid[w]) continue;
c += compute_ssize(G[v][i], v);
}
ssize[v] = c;
return c;
} pair<int, int> search_centroid(int v, int p, int t)
{
pair<int, int> res = make_pair(INT_MAX, -1);
int s = 1, m = 0;
for (int i = 0; i < G[v].size(); ++i){
int w = G[v][i];
if (w == p || centroid[w]) continue;
res = min(res, search_centroid(w, v, t));
m = max(m, ssize[w]);
s += ssize[w];
}
m = max(m, t - s);
res = min(res, make_pair(m, v));
return res;
} void enumerate_mul(int v, int p, pair<ll, ll> d, set<pair<ll, ll> > &ds)
{
if (!ds.count(d)) ds.insert(d);
for (int i = 0; i < G[v].size(); ++i){
int w = G[v][i];
if (w == p || centroid[w]) continue;
enumerate_mul(w, v, MP(d.first + 1, xorr(d.second, val[w])), ds);
}
} bool judge(pair<ll, ll> x, const set<pair<ll, ll> >& tds)
{
if (pre[x.first] == x.second){
return tds.count(MP(m - x.first, post[x.first + 1]));
}
if (post[m - x.first + 1] == x.second){
return tds.count(MP(m - x.first, pre[m - x.first]));
}
return false;
} bool solve(int v)
{
compute_ssize(v, -1);
int s = search_centroid(v, -1, ssize[v]).second;
centroid[s] = true;
for (int i = 0; i<G[s].size(); ++i){
if (centroid[G[s][i]]) continue;
if (ssize[G[s][i]] < m){
continue;
}
if (solve(G[s][i])) {
return true;
}
}
sta.clear();
sta.insert(MP(1, val[s]));
if (m == 1 && val[s] == tar[1]){
return true;
}
set<pair<ll, ll> > tds;
for (int i = 0; i<G[s].size(); ++i){
if (centroid[G[s][i]]) continue;
tds.clear();
enumerate_mul(G[s][i], s, MP(1, val[G[s][i]]), tds);
it = tds.begin();
while (it != tds.end()){
if (judge(*it, sta)){
return true;
}
++it;
}
it = tds.begin();
while (it != tds.end()){
ll one = (*it).first;
ll two = (*it).second;
pair<ll, ll> vv;
if (one > m){
++it; continue;
}
if (pre[one] != two && post[m - one + 1] != two){
++it;
continue;
}
if (tar[one + 1] != val[s] && tar[m - one] != val[s]){
++it;
continue;
}
vv.first = one + 1;
vv.second = (xpow[one] * val[s] % mod + two) % mod;
if (!sta.count(vv)){
sta.insert(vv);
}
++it;
}
}
centroid[s] = false;
return false;
} ll haha[3] = { 37, 23, 53 };
ll tata[2] = { 1000000007, 1000010009 }; int main()
{
int T; cin >> T; int ca = 0;
while (T--)
{
cin >> n;
for (int i = 0; i <= n; ++i) G[i].clear();
int ui, vi;
for (int i = 0; i < n - 1; ++i){
scanf("%d%d", &ui, &vi);
G[ui].push_back(vi);
G[vi].push_back(ui);
}
memset(centroid, 0, sizeof(centroid));
scanf("%s", val + 1);
scanf("%s", tar + 1);
mod_num = haha[rand() % 3];
mod = tata[rand() % 2];
xpow[0] = 1;
for (int i = 1; i <= n; ++i){
xpow[i] = xpow[i - 1] * mod_num%mod;
}
pre[0] = 0;
m = strlen(tar + 1);
for (int i = 1; i <= m; ++i){
pre[i] = (xpow[i - 1] * tar[i] % mod + pre[i - 1]) % mod;
}
post[m + 1] = 0;
for (int i = m; i >= 1; --i){
post[i] = (tar[i] * xpow[m - i] % mod + post[i + 1]) % mod;
}
bool flag = solve(1);
if (flag){
printf("Case #%d: Find\n", ++ca);
}
else{
printf("Case #%d: Impossible\n", ++ca);
}
}
return 0;
}

  

HDU5469 Antonidas(树分治&&哈希)的更多相关文章

  1. hdu4812 逆元+树分治

    逆元链接:https://www.cnblogs.com/zzqc/p/7192436.html 经典的树分治题 #pragma comment("linker,"/STACK:1 ...

  2. hdu-5977 Garden of Eden(树分治)

    题目链接: Garden of Eden Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/ ...

  3. 【BZOJ-1468】Tree 树分治

    1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1025  Solved: 534[Submit][Status][Discuss] ...

  4. HDU 4812 D Tree 树分治+逆元处理

    D Tree Problem Description   There is a skyscraping tree standing on the playground of Nanjing Unive ...

  5. BZOJ 2152: 聪聪可可 树分治

    2152: 聪聪可可 Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一 ...

  6. POJ 1741 Tree 树分治

    Tree     Description Give a tree with n vertices,each edge has a length(positive integer less than 1 ...

  7. UVALive 7148 LRIP【树分治+线段树】

    题意就是要求一棵树上的最长不下降序列,同时不下降序列的最小值与最大值不超过D. 做法是树分治+线段树,假设树根是x,y是其当前需要处理的子树,对于子树y,需要处理出两个数组MN,MX,MN[i]表示以 ...

  8. BZOJ 2566 xmastree(树分治+multiset)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2566 题意:一棵有边权的树.结点有颜色.每次修改一个点的颜色.求每次修改后所有同色 ...

  9. 树分治&树链剖分相关题目讨论

    预备知识 树分治,树链剖分   poj1741 •一棵有n个节点的树,节点之间的边有长度.方方方想知道,有多少个点对距离不超过m 题解 点分治模板题.详见我早上写的http://www.cnblogs ...

随机推荐

  1. 11,flask之--WTForms

    WTForms是什么? 相当于django的ModelForm. 在网页中,为了和用户进行信息交互总是不得不出现一些表单.flask设计了WTForm表单库来使flask可以更加简便地管理操作表单数据 ...

  2. android:windowBackground 和 Android:background 的区别

    通过问别人,我知道了android:windowBackground 和 Android:background的区别 android:windowBackground 一般用于activity启动的时 ...

  3. Android 微信支付步骤

    以前自己写过微信支付,今天让我用h5调用微信支付,结果还浪费了点时间,虽然时间不长. 1.导入jar包 .微信提供的jar包 2.写你的微信支付的代码,其实如果参数都有了就一段代码: public v ...

  4. 《Cracking the Coding Interview》——第13章:C和C++——题目8

    2014-04-25 20:27 题目:实现一个能够通过引用计数来实现自动回收数据的智能指针,用C++,不是java. 解法:这题真心牛,我的第一反应是发呆,因为对引用计数的了解仅限于这个名词,完全没 ...

  5. 《Cracking the Coding Interview》——第7章:数学和概率论——题目7

    2014-03-20 02:29 题目:将质因数只有3, 5, 7的正整数从小到大排列,找出其中第K个. 解法:用三个iterator指向3, 5, 7,每次将对应位置的数分别乘以3, 5, 7,取三 ...

  6. 一个初学者的辛酸路程-继续Django

    问题1:HTTP请求过来会先到Django的那个地方? 先到urls.py  ,里面写的是对应关系,1个URL对应1个函数名. 如果发URL请求过来,到达这里,然后帮你去执行指定的函数,函数要做哪些事 ...

  7. Grid 布局管理器

    Grid 布局管理器: Grid布局类wx.GridSizer,Grid布局以网格形式对子窗口或控件进行摆放,容器被分成大小相等的矩形,一个矩形中放置一个子窗口或控件. wx.GridSizer构造方 ...

  8. 孤荷凌寒自学python第三十二天python的代码块中的异常的捕获

    孤荷凌寒自学python第三十二天python的代码块中的异常的捕获 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天简单了解了Python的错误陷阱,了解到其与过去学过的其它语言非常类似 ...

  9. Wordpress 为用户或角色 role 添加 capabilities(权限)

    首先查看角色具有哪些权限: $admin_role_set = get_role( 'administrator' )->capabilities; $author_role_set = get ...

  10. 201621123034 《Java程序设计》第12周学习总结

    作业12-流与文件 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 面向系统综合设计-图书馆管理系统或购物车 使用流与文件改造你的图书馆管理系统或购物车 ...