NYOJ 685 查找字符串 字典树 map容器 吐血经验 cin cout 与printf scanf

        早上起来本来想先水一题,竟然被水题给虐了,悲剧啊,顺便公布一下水题歌(原创的哦)

白天水一水 不瞌睡,

晚上水一水 睡得香。

饭前水一水 胃口好,

饭后水一水 助消化。

看了oj上一题 查找字符串,感觉有点水(如果数据不坑),水水好心情嘛,用map容器写了写,习惯性的用了map<string,int>,当然还习惯的

用了cin和cout   编译,运行,超时了!!

         顿时感觉是map容器的问题,(这个感觉害了我啊~~)因为map在存入的时候很慢,转念想着用字典树,可行,好换个思路换个方法吧,

字典树,动态的字典树,调试 了半天,提交RE了,怎么调试都是RE,后来崩溃的发现了一个傻逼性质的错误,题中有”+“我把他的ASCII码

写成了46了,原本是43,难怪RE,不过这都是浮云~~

        AC 之后看看比尔的代码顿时崩溃了,和我第一次TLE 的代码几乎一样啊?时间也很少,怎么回事?仔细查看,发现了个很吐血的问题

map<string,int> mp;
char s[16];
gets(s);
mp[s]++;
//......
ptintf("%d\n",mp[s]);

而我的代码用的是

string s;
cin>>s;
mp[s]++;
//.....
cout<<mp[s]<<endl;

测试了一下1000000的测试数据,时间相差竟然1000多ms,一个144,一个1214!!

以后注意啊,

gets比 scanf 快

scanf 比cin快的多,cout也很慢的。。。吐血经验啊,搞了大半个上午了都纠结

题目如下

查找字符串

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 3
描述

小明得到了一张写有奇怪字符串的纸,他想知道一些字符串出现了多少次,但这些字符串太多了,他想找你帮忙,你能帮他吗?输入字符包括所有小写字母、‘@’、‘+’。

输入
第一行包含一个整数T(T<=100).表示测试数据组数。
接下来每组数据第一行包含两个整数n,m(n,m<100000),分别表示有n个字符串,小明要问你m次。
接下来n行,每行包含一个字符串,长度不大于15。
接下来m行,每行包含一个字符串,表示小明要问该串出现的次数。
输出
输出每组小明询问数串出现的次数。
样例输入
1
5 3
hello
it@is+so@easy
hello
ibelieveicanac
hello
hello
icannotacit
Giveup
样例输出
3
0
0
顺便给出字典树的模板,对于本题来讲并不需要释放内存,

字典树模型

 
/*
                字典树模板
    MAX  代表字典树中一共的字符的个数,例如如果只有数字就9,只有小写字母就是26,
        也就是的其中字符的最大ASCII减去最小的加一 ,122-97+1=26;
    下面模板 MAX为80  因为题中除了有小写字母还有“+”(43)和“@”(64)
    122-43+1=80;


*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 80
typedef struct node
{
    struct node *next[MAX]; /*子节点个数 */
    int cnt;
}Trie;

Trie *root; /*定义根节点*/
Trie* build() /*建立新的节点*/
{
    Trie *p=(node *)malloc(sizeof(node));  /*动态分配内存*/
    p->cnt=0;
    for(int i=0;i<MAX;i++)
    {
        p->next[i]=NULL; /*新建节点的子节点为空*/
    }
    return p;
}

int insert(char*s)  /*建树,插入新的字符串*/
{
    Trie *p=root;
    int len=strlen(s);
    for(int i=0;i<len;i++)
    {
        int id=s[i]-'+';/*这里减去的是其中最小的ASCII码对应的字符,这里减‘+'*/
        if(p->next[id]!=NULL)
             p=p->next[id];
        else
        {
            p->next[id]=build();
            p=p->next[id];
        }
    }
    p->cnt++;
    return p->cnt;//灵活改变,可以不返回任何值,看题目问什么
}
int search(char *s)//查找
{
    int len=strlen(s);
    Trie *p=root;
    for(int i=0;i<len;i++)
    {
        int id=s[i]-'+';
        if(p->next[id]!=NULL)
           p=p->next[id];
        else return 0;
    }
    return p->cnt;
}

/*大多的字典树不需要释放内存,但是如果内存不够用,应该还原树空间*/
int deleteTrie(Trie *T)
{
    int i;
    if(T==NULL)return 0;
    for(i=0;i<MAX;i++)
    {
        if(T->next[i]!=NULL)
        deleteTrie(T->next[i]);
    }
    free(T);
    return 0;
}

int main()
{

    int T,n,m,i;
    char s[20];
    scanf("%d",&T);
    while(T--)
    {
        root=build();    //循环的开头需要新建根节点;
        
        scanf("%d%d",&n,&m);
        for(i=0;i<n;i++)
        {
            scanf("%s",s);
            insert(s);
        }
        for(i=0;i<m;i++)
        {
            scanf("%s",s);
            printf("%d\n",search(s));
        }
        deleteTrie(root);//释放空间

    }

	return 0;
}


        

用map容器写代码:

#include<iostream>
#include<cstdio>
#include<map>
#include<string>
using namespace std;
map<string,int>mp;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int m,n;
		char str[18];
		scanf("%d%d",&m,&n);
		a.clear();//记着清空容器
		while(m--)
		{
			scanf("%s",str);
			mp[str]++;
		}
		while(n--)
		{
			scanf("%s",str);
			printf("%d\n",mp[str]);
		}
	}
	return 0;
}       



注意map的写法时间是字典树的二倍!!




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值