题目描述
Doubleville, a small town in Texas, was attacked by the aliens. They have abducted some of the residents and taken them to
the a spaceship orbiting around earth. After some (quite unpleasant) human experiments, the aliens cloned the victims, and released multiple copies of them back in Doubleville. So now it might happen that there are 6 identical person named Hugh F. Bumblebee:
the original person and its 5 copies. The Federal Bureau of Unauthorized Cloning (FBUC) charged you with the task of determining how many copies were made from each person. To help you in your task, FBUC have collected a DNA sample from each person. All copies
of the same person have the same DNA sequence, and different people have different sequences (we know that there are no identical twins in the town, this is not an issue).
根据以上描述信息可以将本题抽象为:给出一给字符串,数量为n,每个字符串的长度为m,输出出现i(1<=i<=n)次的字符串的个数。
解题思路:
最近在学习字典树,刚开始看到这题也想用字典树来做。思考后发现其实可以用更简单的map来实现。定义类型为map<char*, int>的变量,记录字符串出现的次数。然后开辟数组num[20000],记录出现i(1<=i<=n)次的字符串的个数。再遍历map,以当前字符串出现的字数减1记为k作为索引,更新num[k],使得num[k]++。
实现时需要注意的地方:
1、因为在定义map时的key类型是char *,因此需要自定义比较函数。
2、为避免每次都new新的字符串,定义字符数组,需要new的地方,直接从数组中取。
Memory: 1184K Time: 2938MS
#include <cstdio>
#include <map>
#include <cstring>
using namespace std;
struct cmp //自定义比较函数
{
bool operator()(const char *s1, const char *s2) const
{
return strcmp(s1, s2) < 0;
}
};
int main()
{
char *dna;
char dnas[20000][21]; //字符数组,需要new的地方直接取
int num[20000];
map<char*, int, cmp> mp;
int i, j, m, n;
while(scanf("%d%d", &n, &m))
{
if(n == 0 && m == 0)
break;
j = 0;
mp.clear();
for(i = 0; i < n; i++)
{
dna = dnas[j++]; //从数组中直接取
scanf("%s", dna);
mp[dna]++;
}
memset(num, 0, sizeof(num));
map<char*, int, cmp>::iterator iter = mp.begin();
while(iter != mp.end())
{
num[iter->second - 1]++;
iter++;
}
for(i = 0; i < n; i++)
{
printf("%d\n", num[i]);
}
}
return 0;
}
利用map实现,程序的执行效率比较低。有时间再用Trie方法实现,比较两者的效率(猜测Trie肯定比map实现高效)。