• QDU65 again and again(字典序暴力or字典树)


    xx学习了Trie树后,向你问了一个问题,给定一个字符串集合S={str1, str2, ,strn}和一个字符串s,在s的后面接尽量少的字符,使其属于集合S。当然如果s本身就属于Ss就是答案。

    第一行一个正整数T(T <= 10),表示有T组数据。 每组数据输入格式如下: 第一行为一个正整数N(0<N<20000),表示字符串集合内的字符串数。 接下来N行,每行一个字符串,表示集合中的串。 接下来一行是一个正整数Q(0<Q<200),表示有Q次询问。 接下来Q行,每行一个字符串str。 所有字符串均由小写英文字母组成,且1<=长度<=20。

    每组数据输出格式如下: 先输出“Case x:”,x表示是第几组数据,然后输出一个换行。 接下来输出Q行,对于每次询问,如果str能够添加字符使其属于字符串集合,则输出长度最小的(即str添加字符后构成的串),有多个满足条件的话输出字典序最小的。否则输出-1。

    复制
    3
    3
    abc
    abd
    aba
    3
    ab
    ad
    abc
    2
    bcde
    bcdef
    1
    bcd
    3
    abc
    def
    hig
    1
    kkkk
    Case 1:
    aba
    -1
    abc
    Case 2:
    bcde
    Case 3:
    -1

    字典树写法:
    #include <bits/stdc++.h>
    using namespace std;
    int T;
    int N;
    char s[100];
    int dp[500010];
    int NN[500010];
    int ch[500010];
    struct tire
    {
        int L,root,End[500010], Next[500010][27];
        int newnode()
        {
            for(int i=0; i<26; i++)
                Next[L][i] = -1;
            End[L++] = 0;
            return L-1;
        }
        void init()
        {
            L = 0;
            root = newnode();
        }
        void insert(char *tmp)
        {
            int len = strlen(tmp);
            int now = root;
            for(int i=0; i<len; i++)
            {
                if(Next[now][s[i]-'a'] == -1)
                    Next[now][s[i]-'a'] = newnode();
                now = Next[now][s[i]-'a'];
            }
            End[now] = 1;
        }
        void dfs(int now)
        {
            if(End[now] == 1)
            {
                dp[now] = 0;
            }
            for(int i=0; i<26; i++)
            {
                int nn = Next[now][i];
                if(nn != -1)
                {
                    dfs(nn);
                    if(dp[now] > dp[nn] + 1)
                    {
                        dp[now] = dp[nn] + 1;
                        NN[now] = nn;
                        ch[now] = i;
                    }
                    else if(dp[now] == dp[nn] + 1 && ch[now] > i)
                    {
                        NN[now] = nn;
                        ch[now] = i;
                    }
                }
            }
        }
        int query(char *tmp)
        {
            int len = strlen(tmp);
            int now = root;
            for(int i=0; i<len; i++)
            {
                if(Next[now][s[i]-'a'] == -1)
                    return -1;
                now = Next[now][s[i]-'a'];
            }
            return now;
        }
    } Trie;
    int q;
    int main()
    {
        cin>>T;
        int icase = 0;
        while(T--)
        {
            memset(NN, -1, sizeof(NN));
            memset(ch, -1, sizeof(ch));
            memset(dp, 0x3f3f3f3f, sizeof(dp));
            cin>>N;
            Trie.init();
            for(int i=1; i<=N; i++)
            {
                scanf("%s", s);
                Trie.insert(s);
            }
            Trie.dfs(Trie.root);
            cin>>q;
            printf("Case %d:
    ", ++icase);
            while(q--)
            {
                scanf("%s", s);
                int res = Trie.query(s);
                if(res == -1)
                {
                    printf("-1
    ");
                    continue;
                }
                printf("%s", s);
                while(true)
                {
                    if(Trie.End[res] == 1) break;
                    printf("%c", (char)(ch[res] + 'a'));
                    res = NN[res];
                }
                printf("
    ");
            }
        }
        return 0;
    }

    暴力写法:

    #include <bits/stdc++.h>
    using namespace std;
    
    struct Node
    {
        char str[25];
        int len;
    };
    
    Node node[20010];
    
    bool cmp(Node x, Node y)
    {
        return (x.len < y.len || (x.len == y.len && strcmp(x.str, y.str) < 0));
    }
    
    int main()
    {
        int t, tt = 1;
        scanf("%d", &t);
        while(t--)
        {
            int n;
            scanf("%d", &n);
            for(int i = 1; i <= n; i++)
            {
                scanf("%s", node[i].str);
                node[i].len = strlen(node[i].str);
            }
            sort(node + 1, node + 1 + n, cmp);
            int q;
            printf("Case %d:
    ", tt++);
            scanf("%d", &q);
            while(q--)
            {
                char str[25];
                scanf("%s", str);
                int i;
                for(i = 1; i <= n; i++)
                {
                    if(strstr(node[i].str, str) == node[i].str)
                    {
                        printf("%s
    ", node[i].str);
                        break;
                    }
                }
                if(i == n + 1) printf("-1
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    C/C++ 构造函数不能是虚函数
    C/C++ STL迭代器失效
    Linux fork函数
    算法和数据结构 限流算法
    数据库 redis底层实现
    C/C++ 虚析构函数
    万物皆可 Serverless 之使用云函数 SCF 快速部署验证码识别接口
    万物皆可 Serverless 之使用云函数 SCF+COS 免费运营微信公众号
    腾讯云云函数 SCF 日志检索最佳实践
    江娱互动「世界争霸」产品迁移至腾讯云云函数的实践
  • 原文地址:https://www.cnblogs.com/d-e-v-i-l/p/5097947.html
Copyright © 2020-2023  润新知