最短前缀 OpenJ_Bailian - 2797 (字典树)

https://vjudge.net/problem/OpenJ_Bailian-2797

书上说这题用贪心能写, 我想了半天越想越复杂, 其实用数据结构的话反而会更加简单

字典树是一种很基础的树, 就是把多个单词的每个字母拆分成树的一条枝, 重复字母的次数记在节点num值中, 对于很多问题可以大大简化求解步骤

比如此题来说, 我们为输入的多个单词建立一个字典树, 然后对于每个字符串的每个字母我们都查找到其节点num值为1(即只出现了一次), 就说明是该字符串的最短前缀

//最短前缀
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 1010;
struct Trie{
    Trie *next[26];
    int num; //该字母是多少个单词的前缀
}root;
void ainit(Trie* node) //初始化字典树
{
    for(int i = 0; i < 26; i++)
        node -> next[i] = NULL;
    node->num=0;
}
void ainsert(char* str) //插入str到字典树中
{
    Trie *p = &root;
    for(int i = 0; str[i]; i++){
        int t= str[i]-'a';
        if(p->next[t] == NULL){ //如果该字母第一次出现, 建立子树
            p->next[t] = new Trie;
            ainit(p->next[t]);
        }
        p = p->next[t];
        p->num++;
    }
}
void afind(char* str)
{
    Trie *p = &root;
    for(int i = 0; str[i]; i++){
        int t = str[i] - 'a';
        //如果整个单词树遍历完也没有找到num为1的节点就输出自己
        if(p->next[t] == NULL) return;
        p = p->next[t];
        printf("%c",str[i]); //每次都输出一点儿
        //如果找到num为1的前缀直接输出
        if(p->num==1) return;
    }
}

int main()
{
    ainit(&root);
    int n = 0;
    char alpha[maxn][25];
    while(scanf("%s",alpha[n])!=EOF){
        ainsert(alpha[n]);
        n++;
    }
    //查找最短字符
    for(int i = 0; i < n; i++){
        printf("%s ",alpha[i]);
        afind(alpha[i]);
        printf("\n");
    }
}

参考博客: https://blog.csdn.net/u013129143/article/details/82996375

https://www.cnblogs.com/justinh/p/7716421.html

猜你喜欢

转载自blog.csdn.net/a1097304791/article/details/83065068