zoukankan      html  css  js  c++  java
  • HDU5469 Antonidas

    题目

    分析

    拼接字符串,显然是字符串哈希来维护这个信息。

    于是把所有的前缀哈希串预处理一下,再预处理每一个前缀对应的后缀哈希串,然后就可以直接询问当前的串作为后缀是否可以有一个前缀,以及当前作为前缀是否存在后缀。

    然后就做完了。

    代码

    口胡的,题解代码:

    #include<bits/stdc++.h>
    #define MAXN 10010
    #define P 131
    #define ull unsigned long long
    using namespace std;
    const int INF = 0x3f3f3f3f;
    char val[MAXN],s[MAXN];//val为节点字母串,s为待匹配串
    int len;//len为待匹配串的长度
    int n;
    ull pw[MAXN],pre[MAXN],sub[MAXN];//记录幂值,s前缀hash值,s后缀hash值
    int tot,head[MAXN];
    struct edge
    {
        int v,nxt;
    }edg[MAXN << 1];
    inline void addedg(int u,int v)
    {
        edg[tot].v = v;
        edg[tot].nxt = head[u];
        head[u] = tot++;
    }
    int root,ms,sz[MAXN],Size;
    bool vis[MAXN];
    void getroot(int u,int f)//获得重心
    {
        sz[u] = 1;
        int v,mson = 0;
        for(int i = head[u];i != -1;i = edg[i].nxt)
        {
            v = edg[i].v;
            if(vis[v] || v == f) continue;//剔除已经被分治过的点
            getroot(v,u);
            sz[u] += sz[v];
            if(sz[v] > mson) mson = sz[v];
        }
        if(Size - sz[u] > mson) mson = Size-sz[u];//把u看作根节点时u的父亲那一部分也算作子树
        if(ms > mson) ms = mson,root = u;//更新重心
    }
    struct node
    {
        ull hs;//dis链为从节点往重心的hash值
        int dep;//dep为深度
    }dis[MAXN];
    int cnt;
    bool ans;//记录答案
    bool vispre[MAXN],vissub[MAXN];//记录s某个长度的前缀和后缀是否可以得到
    int idpre[MAXN],idsub[MAXN],cpre,csub;//记录哪些长度被标记了,方便重置vispre,vissub
    inline void getdis(int u,int f,ull d,int dep)
    {
        ull w = d+(val[u]-'a'+1)*pw[dep];
        dis[++cnt] = node{w,dep+1};
        int v;
        for(int i = head[u];i != -1;i = edg[i].nxt)
        {
            v = edg[i].v;
            if(v == f || vis[v])
                continue;
            getdis(v,u,w,dep+1);
        }
    }
    inline void solve(int u,int ssize)
    {
        vis[u] = 1;
        cpre = csub = 0;
        if(val[u]-'a'+1 == pre[1] && !vispre[1])
            vispre[1] = true,idpre[++cpre] = 1;
        if(val[u]-'a'+1 == sub[len] && !vissub[len])
        {
            if(vispre[len])
                ans = true;
            vissub[len] = true,idsub[++csub] = len;
        }
        int v;
        for(int i = head[u];i != -1;i = edg[i].nxt)
        {
            v = edg[i].v;
            if(vis[v]) continue;
            cnt = 0;
            getdis(v,u,val[u]-'a'+1,1);
            for(int j = 1;j <= cnt;++j)
            {
                if(dis[j].hs == pre[dis[j].dep] && vissub[dis[j].dep])
                    ans = true;
                if(dis[j].hs == sub[len-dis[j].dep+1] && vispre[len-dis[j].dep+1])
                    ans = true;
            }
            for(int j = 1;j <= cnt;++j)
            {
                if(dis[j].hs == pre[dis[j].dep] && !vispre[dis[j].dep])
                    vispre[dis[j].dep]= true,idpre[++cpre] = dis[j].dep;
                if(dis[j].hs == sub[len-dis[j].dep+1] && !vissub[len-dis[j].dep+1])
                    vissub[len-dis[j].dep+1] = true,idsub[++csub] = len-dis[j].dep+1;
            }
        }
        for(int i = 1;i <= cpre;++i)
            vispre[idpre[i]] = false;
        for(int i = 1;i <= csub;++i)
            vissub[idsub[i]] = false;
        for(int i = head[u];i != -1;i = edg[i].nxt)
        {
            v = edg[i].v;
            if(vis[v]) continue;
            ms = INF;
            Size = sz[v] < sz[u] ? sz[v]:(ssize-sz[u]);
            getroot(v,v);
            solve(root,Size);
        }
    }
    inline void init()
    {
        ms = INF,Size = n;
        memset(vis,false,sizeof(bool)*(n+1));
        memset(head,-1,sizeof(int)*(n+1));
        tot = 0;
        ans = false;
    }
    inline void inithash()
    {
        pw[0] = 1,pre[0] = sub[len+1] = 0;
        for(int i = 1;i <= len;++i)
        {
            pw[i] = pw[i-1] * P;
            pre[i] = pre[i-1] * P + s[i] - 'a' + 1;
            sub[len-i+1] = sub[len-i+2] * P + s[len-i+1] - 'a' + 1;
        }
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        for(int cas = 1;cas <= t;++cas)
        {
            scanf("%d",&n);
            init();
            int u,v;
            for(int i = 1;i < n;++i)
            {
                scanf("%d%d",&u,&v);
                addedg(u,v),addedg(v,u);
            }
            scanf("%s%s",val+1,s+1);
            len = strlen(s+1);
            inithash();
            getroot(1,1);
            solve(root,Size);
            printf("Case #%d: ",cas);
            if(ans)
                printf("Find
    ");
            else
                printf("Impossible
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    Overloaded的方法是否可以改变返回值的类型
    parseXXX的用法
    java的类型转换问题。int a = 123456;short b = (short)a;System.out.println(b);为什么结果是-7616?
    UVA 10405 Longest Common Subsequence(简单DP)
    POJ 1001 Exponentiation(大数处理)
    POJ 2318 TOYS(计算几何)(二分)
    POJ 1265 Area (计算几何)(Pick定理)
    POJ 3371 Flesch Reading Ease (模拟题)
    POJ 3687 Labeling Balls(拓扑序列)
    POJ 1094 Sorting It All Out(拓扑序列)
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14738449.html
Copyright © 2011-2022 走看看