HDOJ 5469 Antonidas 树分治

来源:互联网 发布:淘宝元旦有活动吗 编辑:程序博客网 时间:2024/06/05 23:05

经典的树分治,找字符串用hash找就行了....

#include <bits/stdc++.h>using namespace std;typedef long long LL;#define mp(x, y) make_pair(x, y)const int maxn = 10005;const int maxm = 20005;const int INF = 0x3f3f3f3f;const int mod = 1e9+7;const LL x = 1e6+3;struct Edge{        int v;        Edge *next;}*H[maxn], *edges, E[maxm];vector<pair<LL, int> > dis;bool isp[maxn];bool iss[maxn];int pre[maxn];int suf[maxn];char s[maxn];char a[maxn];bool done[maxn];int size[maxn];int mx[maxn];LL xp[maxn];int n, root, nsize, ans, ml;LL powmod(LL a, LL b){        LL res = 1, base = a;        while(b) {                if(b % 2) res = res * base % mod;                base = base * base % mod;                b /= 2;        }        return res;}void addedges(int u, int v){        edges->v = v;        edges->next = H[u];        H[u] = edges++;}void init(){        edges = E;        memset(H, 0, sizeof H);        memset(isp, 0, sizeof isp);        memset(iss, 0, sizeof iss);        memset(done, 0, sizeof done);}void getroot(int u, int fa){        mx[u] = 0, size[u] = 1;        for(Edge *e = H[u]; e; e = e->next) if(!done[e->v] && e->v != fa) {                int v = e->v;                getroot(v, u);                size[u] += size[v];                mx[u] = max(mx[u], size[v]);        }        mx[u] = max(mx[u], nsize - size[u]);        if(mx[u] < mx[root]) root = u;}void getdis(int u, int fa, int dep, LL dist){        if(dep > ml) return;        dis.push_back(mp(dist, dep));        for(Edge *e = H[u]; e; e = e->next) if(e->v != fa && !done[e->v]) {                int v = e->v;                getdis(v, u, dep + 1, (dist + xp[dep] * (a[v]) % mod) % mod);        }}void solve(int u){        if(ans) return;        done[u] = true;        int t = a[u];        if(t == pre[1]) isp[1] = true;        if(t == suf[ml]) iss[ml] = true;        if(ml == 1 && t == pre[1]) ans = 1;                for(Edge *e = H[u]; e; e = e->next) if(!done[e->v]) {                int v = e->v;                dis.clear();                getdis(v, v, 1, a[v]);                for(int i = 0; i < dis.size(); i++) {                        LL t = dis[i].first;                        int tt = dis[i].second;                        if(suf[ml - tt + 1] == t && isp[ml - tt] == true) ans = 1;                        if(pre[tt] == t && iss[tt+1] == true) ans = 1;                }                                for(int i = 0; i < dis.size(); i++) {                        LL t = dis[i].first;                        int tt = dis[i].second;                        t = (t * x + a[u]) % mod;                        tt++;                        if(t == suf[ml - tt + 1]) iss[ml - tt + 1] = true;                        if(t == pre[tt]) isp[tt] = true;                }        }                t = a[u];        if(t == pre[1]) isp[1] = false;        if(t == suf[ml]) iss[ml] = false;                for(Edge *e = H[u]; e; e = e->next) if(!done[e->v]) {                int v = e->v;                dis.clear();                getdis(v, v, 1, a[v] );                for(int i = 0; i < dis.size(); i++) {                        LL t = dis[i].first;                        int tt = dis[i].second;                        t = (t * x + a[u]) % mod;                        tt++;                        if(t == suf[ml - tt + 1]) iss[ml - tt + 1] = false;                        if(t == pre[tt]) isp[tt] = false;                }        }                for(Edge *e = H[u]; e; e = e->next) if(!done[e->v]) {                int v = e->v;                mx[0] = nsize = size[v];                getroot(v, root = 0);                solve(root);        }}void work(){        int u, v;        scanf("%d", &n);        for(int i = 1; i < n; i++) {                scanf("%d%d", &u, &v);                addedges(u, v);                addedges(v, u);        }        scanf("%s", a+1);        scanf("%s", s+1);        ml = strlen(s+1);        for(int i = 1; i <= ml; i++) s[i] -= 'a' - 1;        for(int i = 1; i <= n; i++) a[i] -= 'a' - 1;                pre[0] = suf[ml+1] = 0;        iss[ml+1] = isp[0] = true;        for(int i = 1; i <= ml; i++) pre[i] = (pre[i-1] * x + s[i]) % mod;        for(int i = ml; i >= 1; i--) suf[i] = (suf[i+1] * x + s[i]) % mod;                ans = 0;        mx[0] = nsize = n;        getroot(1, root = 0);        solve(root);                if(ans == 1) printf("Find\n");        else printf("Impossible\n");}int main(){        xp[0] = 1;        for(int i = 1; i < maxn; i++) xp[i] = xp[i-1] * x % mod;        int _;        scanf("%d", &_);        for(int i = 1; i <= _; i++) {                init();                printf("Case #%d: ", i);                work();        }                        return 0;}


0 0
原创粉丝点击