问题描述
一个字符串的前缀是指以给定字符串开头开始的子串。字符串 carbon 的子串是:c,ca,car,carb,carbo,carbon。注意在这道问题中,空串不被认为是前缀,但是每一不空的串都被认为是本身的前缀。在日常用语中,我们倾向于使用前缀来缩写单词。比如,carbohydrate 就常常被缩写为 carb。在这个问题中,给出一个单词的集合,你要找到每一个单词的最短前缀,使得它可以唯一的表示这个单词。
在下面的样例输入中,carbohydrate 可以被缩写为 carboh,但是不可以缩写为 carbo(或者任何更短的前缀),因为单词表里面有其他的单词以 carho 开头。
一个精确匹配将重载一个前缀。例如,单词 car 的前缀 car 确实匹配到了这个单词。因此,car 作为 car 的一个缩写是没有歧义的,不会表示 carriage 或者任何单词表中以 car 开头的单词。
输入
输入包含至少一,至多 1000 行。每行包含一个由 1 到 20 个字母表示的单词。
输出
输出应该包含与输入同样多的行。输出的每行包含对应输入行的单词,接下来是一个空格和唯一标识这个单词的缀(没有歧义)。
思路
数据小,可以暴力,不然就字典树。
代码
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
const int MAXN = 1024;
const int MAXW = 25;
typedef char string[MAXW];
string str[MAXN];
int longestCommonPrefix(string s1, string s2)
{
int i = 0;
int l1 = strlen(s1);
int l2 = strlen(s2);
for (; i < l1 && i < l2 && s1[i] == s2[i]; i++);
return i;
}
int main()
{
int n = 0;
for (; scanf("%s", str[n]) == 1; n++);
for (int i = 0; i < n; i++) {
int k = 0;
for (int j = 0; j < n; j++) {
if (i == j)
continue;
k = std::max(k, longestCommonPrefix(str[i], str[j]));
}
printf("%s ", str[i]);
for (int j = 0; j <= k; j++)
if (str[i][j] != '\0')
putchar(str[i][j]);
putchar('\n');
}
return 0;
}