/*
*Rainto96
*Beijing University of Posts and Telecommunications School of Software Engineering
*http://blog.csdn.net/u011775691
题意:
10000个节点的一颗树
每个节点有个字母
给出目标字符串
求是否存在点对u,v使得u到v的路径上的字母正好组成这个字符串
解法:
就那么搞,前缀记一下,后缀记一下,然后查查缺的部分有没有
查很有讲究
如果用map存hash值的话,常数太大(自己写的也过不了)很难过
其实可以用bool值存遍历过的状态,是这样的,如果发现当前结点到根的字符串恰好是某个前缀或者某个后缀,则把那里的开关打开
查询的话也是查对应的缺的部分开关有没有打开,于是就从带常数的O(1)变为了朴素的O(1)
这里有一些小细节要注意,多测几组样例就好了
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#include <string>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <climits>
using namespace std;
#define pb push_back
#define ALL(x) x.begin(),x.end()
#define VINT vector<int>
#define PII pair<int,int>
#define MP(x,y) make_pair((x),(y))
#define ll long long
#define ull unsigned ll
#define MEM0(x) memset(x,0,sizeof(x))
#define MEM(x,val) memset((x),val,sizeof(x))
#define scan(x) scanf("%d",&(x))
#define scan2(x,y) scanf("%d%d",&(x),&(y))
#define scan3(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
#define scan4(x,y,z,k) scanf("%d%d%d%d",&(x),&(y),&(z),&(k))
#define Max(a,b) a=max(a,b)
#define Min(a,b) a=min(a,b)
using namespace std;
const int MAXN = 10111;
int head[MAXN];//
struct Edge{
int u,v,nxt;
}ed[MAXN*2];
int n;
bool del[MAXN];//
int wt[MAXN];
int newroot;
int maxn=0x3f3f3f3f;
int dfs(int now,int fa,int all,int& newroot , int dep){
wt[now]=1;
int mx=0;
//if(dep>100000) cerr<<"fuck";
for(int i=head[now];i!=-1;i=ed[i].nxt){
int to=ed[i].v;
if(to==fa || del[to]) continue;
int siz=dfs(to,now,all,newroot,dep+1);
Max(mx,siz);
wt[now]+=siz;
}
Max(mx,all-wt[now]);
if(mx < maxn) maxn=mx ,newroot=now;
return wt[now];
}
int searchit(int root,int all){
maxn=0x3f3f3f3f;
dfs(root,-1,all,newroot,1);
return newroot;
}
int ednum=0;//
bool found=false;//
int Len;//
void init(){
MEM(head,-1);
MEM0(del);
ednum=0;
found=false;//
}
const ull MAGIC = 33;
ull mi[MAXN];//
char node[MAXN] , S[MAXN];//
ull hsv;
pair<ull,ull > que[MAXN*3];//
int tail;//
bool st1[MAXN],st2[MAXN];//suf , pre
ull pre[MAXN],suf[MAXN];
//set<ull >st1,st2;//
#define P(x) ((x)-'a'+1)
bool gao(int now,int fa,ull hs,ull ant,int len,int root){
ull here = hs*MAGIC + P(node[now]);
ull anthere = ant + P(node[now])*mi[len-2];
if(here == suf[len]) que[tail++] = MP(len , 1 );
if(anthere == pre[len-1]) que[tail++] = MP(len-1 , 2 );//这里原来是len,2 就错了
if(here == hsv || (here == suf[len] && st2[Len-len]) || (anthere == pre[len-1] && st1[Len-len+1]) ){
found=true;
return true;
}
for(int i = head[now];i!=-1;i=ed[i].nxt){
int to =ed[i].v ;
if(to == fa || del[to]) continue;
if(gao(to,now ,here , anthere , len+1 ,root)) return true;
}
return false;
}
PII Sque[22111];
int Shead=0,Stail=0;
void solve(int rt,int sz){
Shead=0,Stail=0;
Sque[Stail++] = MP(rt,sz);
while(Shead<Stail){
PII now = Sque[Shead++];
int nr = searchit(now.first , now.second);
del[nr] =true;
//cerr<<nr<<endl;
MEM0(st1);
MEM0(st2);
st1[1] = P(node[nr]) == suf[1];//这里是要先开的,根节点的情况,因为可能后缀就只用一个根节点,前缀是不包括根节点的
if(P(node[nr]) == hsv) found=true;
for(int i=head[nr];i!=-1;i=ed[i].nxt){
int to = ed[i].v;
if(del[to]) continue;
tail=0;
if(P(node[nr]) == hsv ) {
found=true;
return;
}
if(gao(to,-1,P(node[nr]),0,2 ,nr)) return;
for(int j=0;j<tail;j++) {
//st1.insert(que[j].first) , st2.insert(que[j].second);
if(que[j].second == 1 ) st1[que[j].first] = true;
else st2[que[j].first] = true;
}
Sque[Stail++] = MP(to,wt[to]);
}
}
}
int main(){
#ifndef ONLINE_JUDGE
//freopen("/home/rainto96/in.txt","r",stdin);
#endif
mi[0] = 1;
for(int i= 1;i<MAXN;i++) mi[i] = mi[i-1]*MAGIC;
int T;scan(T);
for(int Cas= 1;Cas<=T;Cas++){
printf("Case #%d: ",Cas);
scan(n);
init();
for(int i=0;i<n-1;i++){
int u,v;
scan2(u,v);
ed[ednum] = (Edge){u,v,head[u]};
head[u] = ednum++;
ed[ednum] = (Edge){v,u,head[v]};
head[v] = ednum++;
}
scanf("%s",node+1);
scanf("%s",S);
hsv=0;
Len = strlen(S);
for(int i=0;i<Len;i++){
hsv = hsv*MAGIC + S[i]-'a'+1;
pre[i+1] = hsv;
}
ull ttt=0;
for(int i=Len-1 , now=0;i>=0;i--,now++){
ttt += mi[now] * (S[i] - 'a' + 1);
suf[now+1] = ttt;
}
solve(1 ,n );
if(found) puts("Find");
else puts("Impossible");
}
return 0;
}
2015 上海网赛 HDU5469 树分治
最新推荐文章于 2020-01-18 10:29:32 发布