字典树的建立是应该都是一样的
下面是我的做法:
建立完后, 对每一个单词都进行find_string()判断是否符合, 分别对其分成两半, 用j分隔开(左闭右开);
分别find()其子串[0, j+1), [j+1, string_len), 当两子串都找到后,则输出此主串, 然后,break;
一个break也让我WA, 因为如果输入为:aa aaa aaaaa, 输出是aaaaa 和 aaaaa两行.
find()中没有注意到判断i=j(匹配, 但不一定存在此单词), 就直接返回EXIST, 又错了....唉
结果输入aa aaa aaaaa时输出了5、6行...
应该是返回current->exist;(此单词是否存在)...
终于A了...^_^
2010-11-20 10:45:08 Accepted 1247 31MS 7324K 3010 B C Y
#include <stdlib.h>
#include <string.h>
#define ALPH_LEN 26
#define LEN 50000
#define WORD_LEN 100
const int ZERO = 0;
const char FIRST_CHAR = 'a';
const char EXIST = '1';
const char NON_EXIST = '0';
char word[LEN][WORD_LEN];
/* 字典树定义 */
typedef struct node {
struct node *child[ALPH_LEN]; /* 26个元素 */
char exist; /* exist:'1' 表示存在此单词, '0'不存在 */
}node, *Node;
Node root; /* 字典树根结点(不存储任何元素) */
void insert(char *str)
{
int i, index, len;
Node current = NULL, newnode = NULL; /* 当前结点和新增单词的首元素 */
len = strlen(str);
if (ZERO == len) /* 单词长度为0, 无须插入 */
{
return;
}
current = root; /* 每一次插入都要从根结点开始 */
for (i = 0; i < len; i++)
{
index = str[i] - FIRST_CHAR; /* 获取此字母的下标 */
if (current->child[index] != NULL) /* 存在此字母 */
{ /* 修改当前结点 */
current = current->child[index];
}
else
{
newnode = (Node) calloc (1, sizeof(node));
if (NULL == newnode)
{
printf("空间分配失败!\n");
exit(-1);
}
current->child[index] = newnode; /* 插入新增结点 */
current = newnode; /* 修改当前结点 */
}
}
current->exist = EXIST; /* 新增单词已存在字典树中 */
}
/* 查找单词, 存在返回EXIST, 否则返回NON_EXIST */
char find(const char *str, int i, int j)
{
int index;
Node current;
if (i >= j) /* 此单词不存在 */
{
return NON_EXIST;
}
current = root; /* 每一次遍历都要从根结点开始 */
while (i < j)
{
index = str[i] - FIRST_CHAR;
if (current->child[index] != NULL) /* 当前字符处于字典树中 */
{
current = current->child[index]; /* 修改当前位置 */
}
else
{
return NON_EXIST;
}
i++;
}
return current->exist; /* 是当前单词存在与否,而不是EXIST!!! */
}
/* 查找符合的主串 */
void find_string(Node root, int len)
{
int i, j, word_len;
for (i = 0; i < len; i++) /* 每一个单词都判断一次 */
{
word_len = strlen( word[i] ); /* 此单词长度 */
for (j = 0; j < word_len; j++)
{
if (find(word[i], 0, j + 1) == EXIST) /* 判断前辍 */
{
if (find(word[i], j + 1, word_len) == EXIST) /* 判断后辍 */
{
printf("%s\n", word[i]);
break;
/* 一个break也让我WA, 因为如果输入为:aa aaa aaaaa, 输出是aaaaa 和 aaaaa两行 */
}
}
}
}
}
/* 释放内存 */
void release(Node root)
{
int i;
if (NULL == root) /* 此结点为空, 不需要释放 */
{
return;
}
for (i = 0; i < ALPH_LEN; i++)
{
if (root->child[i] != NULL)
{
release(root->child[i]);
}
}
free( root );
root = NULL;
}
int main()
{
int i;
char string[WORD_LEN];
if ((root=(Node) calloc (1, sizeof(node))) == NULL) {
printf("空间分配失败!\n");
exit(-1);
} /* 根结点分配空间 */
i = 0;
while (scanf("%s", string) != EOF)
{
insert( string ); /* 插入 */
strcpy(word[i], string);
i++;
}
find_string(root, i); /* 查找符合的单词 */
release( root ); /* 清理资源 */
return 0;
}
/*
A hat’s word is a word in the dictionary that is
the concatenation of exactly two other words in the dictionary.
You are to find all the hat’s words in a dictionary.
Input
Standard input consists of a number of lowercase words, one per line,
in alphabetical order. There will be no more than 50,000 words.
Only one case.
Output
Your output should contain all the hat’s words, one per line, in alphabetical order.
Sample Input
a
ahat
hat
hatword
hziee
word
Sample Output
ahat
hatword
*/