hdu 1251(字典树)(3种方法)

统计难题

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 39200    Accepted Submission(s): 14274


Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
 

Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.

注意:本题只有一组测试数据,处理到文件结束.
 

Output
对于每个提问,给出以该字符串为前缀的单词的数量.
 

Sample Input
banana band bee absolute acm ba b band abc
 

Sample Output
2 3 1 0
  

       这个题就是建立普通的字典树,首先读入单词,建立树,然后每行一个询问,输出以这个询问为前缀的单词数量(若单词本身就是前缀,那么这个单词也要计数)。

      处理数据时注意:1.以一空行作为单词输入结束.

                                 2.若用静态数组的方法建树,数组要开大点,比如500000,开小了就是runtime error


第一种方法:静态数组法

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAX=26;
const int MAXN=500000;
int  tree[MAXN][MAX];
int   val[MAXN];
int node;
void Insert(char s[])
{
    int i,tmp;
    int rt=0;
    for(i=0; s[i]; i++)
    {
        tmp=s[i]-'a';
        if(tree[rt][tmp]==0)
        {
            tree[rt][tmp]=++node;
        }
        rt=tree[rt][tmp];
        val[rt]++;
    }
}
int Search(char s[])
{
    int rt=0;
    int i=0,tmp;
    while(s[i])
    {
        tmp=s[i]-'a';
        i++;
        if(tree[rt][tmp]==0)return 0;
        rt=tree[rt][tmp];
    }
    return val[rt];
}
int main()
{
    int i;
    node=0;
    char str[22];
    memset(val,0,sizeof(val));
    memset(tree,0,sizeof(tree));
      while(gets(str),strcmp(str,""))
     Insert(str);
     while (gets(str))
     {
        printf("%d\n", Search(str));
     }
     return 0;
}

第二种方法:指针法建树

#include<string.h>
#include<iostream>
#include<stdio.h>
using namespace std;
struct node
{
    bool is;
    int cnt;
    node *next[27];
    node()
    {
        is=false;
        cnt=0;
        memset(next,0,sizeof(next));
    }
};
void Insert(node *rt,char s[])
{
    node *p=rt,*newnode;
    int i=0,tmp;
    int ok=1;
    for(i=0; i<strlen(s); i++)
    {
        tmp=s[i]-'a';
        if(p->next[tmp]==NULL)
        {
            newnode=new node();
            p->next[tmp]=newnode;
        }
        p=p->next[tmp];
        p->cnt++;
    }
    p->is=true ;
}
int Search(node *rt,char s[])
{
    node *p=rt;
    int i=0,tmp;
    for(i=0; i<strlen(s); i++)
    {
        tmp=s[i]-'a';
        if(p->next[tmp]==NULL)return 0;
        p=p->next[tmp];
    }
    return p->cnt;
}

int main()
{
    int i=0;
    node *rt=new node();
       char str[20];
    while(gets(str),strcmp(str,""))
    Insert(rt,str);
    while(gets(str)!=NULL)
    printf("%d\n",Search(rt,str));
    return 0;

}

第三种方法:可以使用map的方法(看别的网友代码时发现的)

#include <cstdio>
#include <iostream>
#include <map>
#include <cstring>
#include <string>
using namespace std;

int main()
{
	char str[17];
	map<string, int> m;
	while(gets(str))
	{
		int len = strlen(str);
		if (!len)
		{
			break;
		}
		for(int i = len; i > 0; i--)
		{
			str[i] = '\0';
			m[str]++;
		}
	}
	while(gets(str))
	{
		cout<<m[str]<<endl;
	}

	return 0;
}



posted on 2017-09-19 23:09  横济沧海  阅读(102)  评论(0编辑  收藏  举报

导航