字典树 之 hdu 1671 poj 3630

之前所写代码在 poj 3630 题无法AC,现换另外一种实现方式,hdu、poj 皆可AC。

(poj无法AC原因:动态分配内存空间花费时间较多,导致超时)

一、题目:

若存在其中一个电话的符号串是另一个电话的前缀,则定义为: this list would not be consistent. 输出:NO

否则,输出:YES。


二、思考:

考虑两种情况:

(1)若每个符号串在建立串的过程中,

         1)有其他串,作为该符号串子串,输出:NO (代码中:Ju2 = true)

         2)该符号串作为其他串的子串,输出:NO  (代码中 Ju1 = true )

(2)不满足(1),输出:YES


三、解法:

在字典树中加一个 bool 变量,用于判断当前节点是否作为一个电话符号串的结尾字符。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX = 10;

int Trie_pos;

struct Trie {
    bool Judge;
    Trie *next[MAX];
};

Trie Memory[100000];

Trie *Root;

Trie* CreTrie_ptr()
{
    Trie* p;
    p = &Memory[Trie_pos++];
    p->Judge = false;
    memset(p->next, NULL, sizeof(p->next));
    return p;
}

bool Cre_Judge_Trie(char *str)
{
    bool Ju1 = true, Ju2 = false;
    int len = strlen(str);
    Trie *p = Root;
    for (int i = 0; i < len; ++i) {
        int pos = str[i] - '0';
        if (!(p->next[pos])) {
            Ju1 = false;
            p->next[pos] = CreTrie_ptr();
        } else {
            if (p->next[pos]->Judge) {
                Ju2 = true;
                break;
            }
        }
        p = p->next[pos];
    }
    p->Judge = true;
    return (Ju1 || Ju2);
}

int main()
{
    //freopen("input.txt", "r", stdin);
    int t;
    scanf("%d", &t);
    while (t--) {
        Trie_pos = 0;
        Root = CreTrie_ptr();
        int n;
        scanf("%d", &n);
        char add_ch[10000][10];
        for (int j = 0; j < n; j++) {
			scanf("%s", add_ch[j]);
        }
        int i;
        for (i = 0; i < n; i++) {
            if (Cre_Judge_Trie(add_ch[i])) {
                printf("NO
");
                break;
            }
        }
        if (i == n) {
            printf("YES
");
        }
    }
    return 0;
}



原文地址:https://www.cnblogs.com/shijianming/p/4140842.html