做了一道POJ 2001,對TRIE樹的思想差不多理解了。其實TRIE樹的思想很簡單,就是建樹,每個節點都有26個子節點(如果是數字的話,那就是10個),然後每個單詞從頭到尾按照樹的深度找下去,最後所有這些單詞就掛在TRIE樹上啦。
對於TRIE樹的操作有:插入、刪除、搜索等等。每個操作都很重要,刪除如果沒有的話在多組數據中就基本上要MLE了,這道題就是這樣,一開始我沒有做刪除操作,MLE了5次。
題意:給你n個數(n <= 10000),問這些數中有沒有某個數是另一個數的前綴,比如111和1110。有就輸出NO,否則就輸出YES。
思路很簡單:因爲是前綴,因此可以維護TRIE樹,維護好之後,再去從TRIE樹上找每個數字,如果某個數字已經找到它應該到的結點之後,還能再往下找到其他的數,那就說明滿足題目說的條件了,退出判斷即可。這種字符串匹配的題目,一開始可能會想到KMP,但是想想如果每個字符都和其他字符去做一遍KMP,那得O(n^2)的複雜度,肯定是要超時的。
順便吐一個自己的槽,指針沒學好真傷不起,malloc和free都用得不溜。
Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
char a[10001][11];
struct node
{
struct node *next[10];
};
void insert(node *root, const char *tar)
{
if(root == NULL || *tar == '\0')
return;
int id;
node *p = root;
while(*tar)
{
id = *tar - '0';
if(p -> next[id] == NULL)
{
node *temp = (node *)malloc(sizeof(node));
for(int i = 0; i < 10; i ++)
temp -> next[i] = NULL;
p -> next[id] = temp;
}
p = p -> next[id];
tar ++;
}
}
bool search(node *root, const char *tar)
{
int id;
node *p = root;
while(*tar && p != NULL)
{
id = *tar - '0';
p = p -> next[id];
tar ++;
}
for(int i = 0; i < 10; i ++)
if(p -> next[i] != NULL)
return true;
return false;
}
void delnode(node *tar)
{
int i;
for(int i = 0; i < 10; i ++)
{
if(tar -> next[i] != NULL)
delnode(tar -> next[i]);
}
free(tar);
}
int main()
{
int cse, t = 1;
scanf("%d", &cse);
while(cse --)
{
node *root = (node *)malloc(sizeof(node));
for(int i = 0; i < 10; i ++)
root -> next[i] = NULL;
scanf("%d", &n);
for(int i = 0; i < n; i ++)
{
scanf("%s", a[i]);
insert(root, a[i]);
}
bool yes = true;
for(int i = 0; i < n; i ++)
if(search(root, a[i]))
{
yes = false;
break;
}
if(yes)
printf("Case %d: YES\n", t ++);
else
printf("Case %d: NO\n", t ++);
delnode(root);
}
}