在一个树上 (1≤N≤104) 匹配字符串
直接暴力树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:
对于树的重心 root ,匹配出经过 root 的串,然后再减去 v→root→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;
}