Tri树 统计难题

统计难题

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

 

Problem Description

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

Input

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

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

Output

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

Sample Input

banana

band

bee

absolute

acm

ba

b

band

abc

Sample Output

2 3 1 0

Ignatius.L   |   We have carefully selected several similar problems for you:  1075 1247 1671 1298 1800 

字典树,查询字符串是多少个单词的前缀。加上个d数组记录当前节点是多少个单词的前缀。

这题最好用链表做,数组很容易超空间或者开小,WA和MLE都很烦人。

放上个自己写的链表:

#include <iostream>
#include <string.h>
#include <string>
#include <stdio.h>
using namespace std;

struct node                //定义结构体表示Tri树上的节点
{
	node* next[27];       //子节点
	int v;                //记录当前节点是几个单词的前缀
};
node root;
node *newnode()             //新建一个节点
{
	node * temp=new node;
	temp->v=1;                          
	for (int i = 0; i < 27; i++)
	{
		temp->next[i]=NULL;
	}
	return temp;
}

int size;

void insert(char *s){
    int len=strlen(s), v;
    node *p=&root;
    for (int i = 0; i < len; i++)
    {
        v=s[i]-'a';
        if (p->next[v]==NULL)           //没有这个节点就新建一个节点,且一定是一个单词的前缀
        	p->next[v]=newnode();
        else p->next[v]->v++;              //如果已经有了就把前缀数加一
        p=p->next[v];
    }
}

int search(char *s)
{
    int len=strlen(s), v;
    node *p=&root;
    for (int i = 0; i < len; i++)
    {
        v=s[i]-'a';
        p=p->next[v];
        if (p==NULL)              //查询不到这个字符串则是0个单词的前缀
        	return 0;
    }
    return p->v;          //否则输出前缀数
}

int main()
{
    char s[20];

    size=0;
    while (gets(s) && s[0]!='\0')
        insert(s);                        //建树
    
    while (scanf("%s", &s)!=EOF)
    {
        int ans=search(s);             //查询
        printf("%d\n", ans);
    }

    return 0;
}

下面这个是非链表的写法,卡常卡了好久=_=

#include <iostream>
#include <string.h>
#include <string>
#include <stdio.h>
using namespace std;
const int maxn=5*1e5+10;

int size, nex[maxn][27], d[maxn];
bool val[maxn];

void insert(char *s){
    int u=0, len=strlen(s), v;
    for (int i = 0; i < len; i++)
    {
        v=s[i]-'a';
        if (nex[u][v]==0)
        {
            size++;
            nex[u][v]=size;
            d[size]=1;
            val[size]=0;
        }
        else d[nex[u][v]]++;
        u=nex[u][v];
    }
    val[u]=1;
}

int search(char *s)
{
    int u=0, len=strlen(s), v;
    for (int i = 0; i < len; i++)
    {
        v=s[i]-'a';
        if (nex[u][v]==0) return 0;
        u=nex[u][v];
    }
    return d[u];
}

int main()
{
    char s[20];

    size=0;
    memset(nex, 0, sizeof(nex));
    memset(d, sizeof(d), 0);
    while (gets(s) && s[0]!='\0')
        insert(s);
    
    while (scanf("%s", &s)!=EOF)
    {
        int ans=search(s);
        printf("%d\n", ans);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41703679/article/details/81705386
今日推荐