HDU 5469(Antonidas-树上匹配字符串)
2015-09-28 21:27
399 查看
在一个树上(1≤N≤104)(1≤N≤10^4)匹配字符串
直接暴力树dp用map存,
时间可卡过,记得递归后清map防止MLE
我们还可以使用树分治和hash:
对于树的重心rootroot,匹配出经过rootroot的串,然后再减去v→root→vv \to root\to v的串,得到答案,否则继续分治。
直接暴力树dp用map存,
时间可卡过,记得递归后清map防止MLE
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<set> #include<cctype> #include<ctime> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=next[p]) #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (100000007) #define MAXN (10000+10) #define MAXM (20000+10) typedef long long ll; ll mul(ll a,ll b){return (a*b)%F;} ll add(ll a,ll b){return (a+b)%F;} ll sub(ll a,ll b){return (a-b+(a-b)/F*F+F)%F;} void upd(ll &a,ll b){a=(a%F+b%F)%F;} int n; char c[MAXN]; char s[MAXN],s2[MAXN]; bool flag=0; class link_table { public: void mem() { MEM(pre) MEM(edge) MEM(pre) MEM(weight) size=1; } int edge[MAXM],next[MAXM],pre[MAXN],weight[MAXM],size; int n; void addedge(int u,int v,int w) { edge[++size]=v; weight[size]=w; next[size]=pre[u]; pre[u]=size; } void addedge2(int u,int v,int w){addedge(u,v,w);addedge(v,u,w);} set<int> f[MAXN],g[MAXN]; void dfs(int x,int fa) { Forp(x) { int v=edge[p]; if (v==fa) continue; dfs(v,x); set<int>::iterator it=f[v].begin(); for(;it!=f[v].end();it++) { int p=(*it); if (s[p+1]==c[x]) { f[x].insert(p+1); } } f[v].clear(); it=g[v].begin(); for(;it!=g[v].end();it++) { int p=(*it); if (s2[p+1]==c[x]) { g[x].insert(p+1); } } g[v].clear(); } if (c[x]==s[1]) f[x].insert(1); if (c[x]==s2[1]) g[x].insert(1); set<int>::iterator it; for (it=f[x].begin();it!=f[x].end();it++) { if (g[x].find(::n-(*it)+1)!=g[x].end()) { flag=1; break; } } } }St; int main() { // freopen("1002.in","r",stdin); int T;cin>>T; For(kcase,T) { flag=0; St.mem(); cin>>St.n; For(i,St.n-1) { int x,y; scanf("%d%d",&x,&y); St.addedge2(x,y,1); } For(i,St.n) { St.f[i].clear(); St.g[i].clear(); } scanf("%s",c+1); scanf("%s",s+1); n=strlen(s+1); For(i,n) s2[i]=s[n-i+1]; St.dfs(1,0); St.f[1].clear();St.g[1].clear(); if (flag) printf("Case #%d: Find\n",kcase); else printf("Case #%d: Impossible\n",kcase); } return 0; }
我们还可以使用树分治和hash:
对于树的重心rootroot,匹配出经过rootroot的串,然后再减去v→root→vv \to root\to v的串,得到答案,否则继续分治。
#include<bits/stdc++.h> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define ForkD(i,k,n) for(int i=n;i>=k;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=Pre[x];p;p=Next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=next[p]) #define Lson (o<<1) #define Rson ((o<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (100000007) #define MAXT (200+10) #define MAXN (100000+10) #define pb push_back #define mp make_pair typedef long long ll; typedef unsigned long long ull; char C[MAXN],S[MAXN]; ull hPre[MAXN],hSuf[MAXN]; ull B[MAXN],base=31; int n,len; int Pre[MAXN],Next[MAXN*2],edge[MAXN*2],siz=1; void addedge(int u,int v){ edge[++siz]=v; Next[siz]=Pre[u]; Pre[u]=siz; } void addedge2(int u,int v) {addedge(u,v),addedge(v,u);} int fa[MAXN],sz[MAXN],vis[MAXN]; int que[MAXN]; int getroot(int root) { int l=1,r=1; que[1]=root;fa[root]=0; while(l<=r) { int now=que[l]; Forp(now) { int v=edge[p]; if (fa[now]==v||vis[v]) continue; fa[v]=now; que[++r]=v; } ++l; } int res=INF; do { int now=que[r],m=0; sz[now]=1; Forp(now) { int v=edge[p]; if (fa[now]==v||vis[v]) continue; sz[now]+=sz[v]; m=max(m,sz[v]); } m=max(m,l-1-sz[now]); if (res>m) { res=m; root=now; } } while (--r); return root; } int used[MAXN]; int dis[MAXN]; ull ldist[MAXN],rdist[MAXN]; int go(int root ,int u) { Rep(i,len+1) used[i]=0; int l=1,r=1; que[1]=u; while(l<=r) { int now=que[l]; if (dis[now]<=len&&ldist[now]==hPre[dis[now]]) used[dis[now]]++; Forp(now) { int v=edge[p]; if (fa[now]==v||vis[v]) continue; fa[v]=now; dis[v]=dis[now]+1; que[++r]=v; ldist[v]=ldist[now]+B[dis[v]]*C[v]; rdist[v]=rdist[now]+B[dis[v]-1]*C[v]; } ++l; } int ans=0; For(i,r) { int now=que[i]; if (dis[now]-1<=len&&hSuf[dis[now]-1] == rdist[now] ) { ans+=used[len+1-dis[now]]; } } return ans; } bool solve(int root) { root=getroot(root); fa[root]=0; vis[root]=1; dis[root]=1; ldist[root]=C[root]; rdist[root]=0; int ans=go(root,root); Forp(root){ int v=edge[p]; if (vis[v]) continue; ans-=go(root,v); } if (ans>0) return 1; Forp(root) { int v=edge[p]; if (vis[v]) continue; if (solve(v)) return 1; } return 0; } void mem() { MEM(Pre) siz=1; MEM(vis) MEM(fa) MEM(sz) MEM(used) } int main() { // freopen("hdu5469.in","r",stdin); // freopen(".out","w",stdout); B[1]=1; Fork(i,2,100000) B[i]=B[i-1]*base; int T;cin>>T; For(kcase,T) { mem(); cin>>n; For(i,n-1) { int u,v; scanf("%d%d",&u,&v); addedge2(u,v); } scanf("%s%s",C+1,S+1); len=strlen(S+1); hPre[0]=hSuf[0]=0; For(i,len) hPre[i]=hPre[i-1]*base+S[i]; reverse(S+1,S+1+len); For(i,len) hSuf[i]=hSuf[i-1]*base+S[i]; int flag=solve(1); if (flag) printf("Case #%d: Find\n",kcase); else printf("Case #%d: Impossible\n",kcase); } return 0; }
相关文章推荐
- ocp-v13-036
- 上千亿的红海市场,如何逆袭出一个新品牌?(80%产品,20%营销,群众路线)
- 沪上各区免费停车场大全
- build.gradle 的设置和相关说明
- HDU 5199/BC 36B Gunner
- 关于Glide——一个高效的图片加载和缓存类库
- [LeetCode-283] Move Zeroes(移动零元素)
- ocp-v13-035
- TFS撤销其他人的迁出
- ios导航栏自定义返回按钮后,多出蓝点bug
- CSS3基础总结
- 条件随机场CRF简介
- Perl文件"filename.pl"在windows 命令行无法执行
- 20150928作业
- OK335xS U-boot 环境变量解析
- xml学习之xml介绍
- HDU 5198 /BC 36A Strange Class
- hdu5476 Explore Track of Point 2015上海网络赛
- hdu5478 Can you find it(数学规律)
- Android 动画配置