1 条题解

  • 1
    @ 2025-5-11 20:33:05

    问题理解

    我们需要为给定的单词列表中的每个单词找到一个最短的前缀,该前缀能够唯一标识该单词。也就是说,这个前缀在单词列表中只出现一次,不会与其他单词的前缀冲突。如果单词本身是唯一的(即没有其他单词以它开头),那么该单词的最短唯一前缀就是它自己。

    解决思路

    数据结构选择:使用Trie(前缀树)数据结构来高效地存储和查询单词的前缀。Trie可以帮助我们快速查找某个前缀是否唯一。 构建Trie: 每个节点表示一个字符,从根节点到某个节点的路径表示一个前缀。 每个节点维护一个计数器cnt,表示有多少单词经过该节点。 插入单词: 对于每个单词,逐个字符插入到Trie中,并在每个经过的节点上增加计数器。 查找最短唯一前缀: 对于每个单词,从根节点开始,逐个字符遍历。 在每个节点检查计数器cnt,如果cnt为1,说明当前前缀是唯一的,可以停止遍历。

    代码实现

    以下是基于上述思路的C++代码实现:

    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<algorithm>
    #define F(i,j,n) for(int i=j;i<=n;i++)
    #define D(i,j,n) for(int i=j;i>=n;i--)
    #define ll long long
    #define pa pair<int,int>
    #define maxn 20005
    #define inf 1000000000
    using namespace std;
     
    struct trie_type {
        int cnt, next[30];
    } t[maxn];
     
    int tot = 0, n = 0;
    char s[1005][25];
     
    inline void insert(char *ch) {
        int p = 0, l = strlen(ch);
        F(i, 0, l - 1) {
            int tmp = ch[i] - 'a';
            if (!t[p].next[tmp]) t[p].next[tmp] = ++tot;
            p = t[p].next[tmp];
            t[p].cnt++;
        }
    }
     
    inline void find(char *ch) {
        int p = 0, l = strlen(ch);
        printf("%s ", ch);
        F(i, 0, l - 1) {
            printf("%c", ch[i]);
            int tmp = ch[i] - 'a';
            p = t[p].next[tmp];
            if (t[p].cnt == 1) break;
        }
        printf("\n");
    }
     
    int main() {
        while (~scanf("%s", s[++n])) insert(s[n]);
        F(i, 1, n - 1) find(s[i]);
        return 0;
    }
    

    代码解释

    Trie结构定义: trie_type结构体表示Trie的节点,包含一个计数器cnt和一个长度为26的数组next,用于存储子节点的索引。 插入函数insert: 遍历单词的每个字符,将字符转换为索引(tmp = ch[i] - 'a')。 如果当前字符对应的子节点不存在,则创建一个新节点。 移动到子节点,并增加该节点的计数器cnt。 查找函数find: 遍历单词的每个字符,逐个输出字符。 在每个节点检查计数器cnt,如果cnt为1,说明当前前缀是唯一的,停止遍历。 主函数main: 读取输入单词,调用insert函数将每个单词插入到Trie中。 调用find函数为每个单词查找最短唯一前缀,并输出结果。

    • 1

    信息

    ID
    1002
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    3
    已通过
    1
    上传者