题目链接:http://poj.org/problem?id=2001
题目大意:给定n个字符串,问每个字符串的最短表示。用这个最短表示就可以把其他字符串区别开来,比如abc和ab,前一个最短表示仍然是abc,后一个任然是ab,如果一个是abcde,一个是abce,那前面一个是abcd,后面一个i是abce。
解题思路:本题可用字段树解。最短表示有两种情况:一种是整个串是其他串的子串,那它的最短表示就是它自己。一种是这个串和其他串有公共前缀,那只要找最长的公共前缀加下一个不一样的字符就可以了。思路很简单,字典树写起来也不复杂。
测试数据:
carbohydrate
cart
carburetor
caramel
caribou
carbonic
cartilage
carbon
carriage
carton
car
carbonate
abb
abb
abcd
ab
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MIN 30
#define MAX 1100
struct node{
int count;
node *next[MIN];
}*root;
char str[MAX][MIN];
node *CreateNode()
{
node *p;
p = (node *) malloc (sizeof(node));
p->count = 1;
for (int i = 0; i < 26; ++i)
p->next[i] = NULL;
return p;
}
void release(node *p){
for (int i = 0; i < 26; ++i)
if (p->next[i] != NULL) release(p->next[i]);
free(p);
}
void insert(char *str){
int i = 0,k;
node *p = root;
while (str[i]) {
k = str[i++] - 'a';
if (p->next[k] == NULL)
p->next[k] = CreateNode();
else p->next[k]->count++;
p = p->next[k];
}
}
void search(char *str){
int i = 0,k,j,flag = 0;
node *p = root;
while (str[i] && !flag) {
k = str[i++] - 'a';
p = p->next[k];
if (p->count == 1) {
flag = 1;
printf("%s ",str);
for (j = 0; j < i; ++j)
printf("%c",str[j]);
printf("\n");
}
}
if (flag == 0)
printf("%s %s\n",str,str);
}
int main()
{
int i = 0,j,k;
root = CreateNode();
for (i = 0; scanf("%s",str[i]) != EOF; ++i)
insert(str[i]);
for (j = 0; j < i; ++j)
search(str[j]);
release(root);
}
本文章ZeroClock原创,但可以转载,因为我们是兄弟。