计算一个字符串数组中有多少个重复字符串出现。
如果直接使用map容器,那么这条题就很简单了,一下就AC了,因为map已经处理好一切了;
不过时间超过1532ms,有点慢。
如下:
int main()
{
map<string, int> msi;
int total = 0;
char treeName[40];
while (gets(treeName))
{
msi[treeName]++;
total++;
}
for (map<string, int>::iterator it = msi.begin(); it != msi.end(); it++)
{
string s = it->first;
printf("%s ", s.c_str());
printf("%.4f\n", (float)(it->second)/(float)total * 100.0f);
}
return 0;
}
使用Trie可以加速到750ms。
本题注意就是节点孩子需要开到256个,十分大,因为输入没有注明是限定在上面字符范围内的,可以是空格,大小字符,也可以使其他字符,反正是ASCII都可能,故此需要开到256.
除此之外,就是一般的Trie操作,只需要使用插入和遍历操作就可以了。
#include <stdio.h>
#include <string.h>
#include <map>
#include <string>
using namespace std;
const int ALP_SIZE = 256;
struct Node
{
int n; //How many times apprear
Node *arr[ALP_SIZE];
Node() : n(0)
{
for (int i = 0; i < ALP_SIZE; i++)
{
arr[i] = NULL;
}
}
~Node()
{
for (int i = 0; i < ALP_SIZE; i++)
{
if (arr[i]) delete arr[i];
}
}
};
Node *Trie; //empty head node, not need for another struct
void insert(char ch[])
{
int len = strlen(ch);
Node *pCrawl = Trie;
for (int i = 0; i < len; i++)
{
int id = ch[i];
//if (' ' == ch[i]) id = 0;
if (pCrawl->arr[id] == NULL)
{
pCrawl->arr[id] = new Node;
}
pCrawl = pCrawl->arr[id];
}
pCrawl->n++;
}
/* 输入字符不知道,故此不能特殊处理
void convertTolowerCase(char name[])
{
int len = strlen(name);
for (int i = 0; i < len; i++)
{
if ('A'<= name[i] && name[i] <= 'Z') name[i] = name[i] - 'A' + 'a';
}
}
*/
int total;
char treeName[40];
void printTrie(Node *r, int i = 0)
{
if (!r) return ;
if (r->n)
{
for (int j = 0; j < i; j++)
{
putchar(treeName[j]);
}
printf(" %.4f\n", (float)(r->n)/(float)total * 100.0f);
}
for (int j = 0; j < ALP_SIZE; j++)
{
if (r->arr[j])
{
treeName[i] = j;
printTrie(r->arr[j], i+1);
}
}
}
int main()
{
Trie = new Node;
total = 0;
while (gets(treeName))
{
insert(treeName);
total++;
}
printTrie(Trie);
delete Trie;
return 0;
}