学习如何使用Hash_map

前两天在没事干做大连海事的马拉松的时候碰到一道这样的题:

Problem Description

Abstract Communication Mastership (ACM) is a software company that develops a unique social network
called tWinter.
Each tWinter user has a handle that starts with a commercial at (‘@’) character. Users of tWinter social
network publish short messages to the network.
If a user’s message contains another user’s handle (preceded by a space or at the beginning of the message,
and followed by a space or at the end of the message) then it is called a mention.
A sequence of messages is called a conversation if each message in the sequence (except the first one)
contains a mention of the author of the previous message in the sequence.
You are hired to find the longest conversation in the given chronological log of messages.

Input

The first line of the input file contains an integer n (1 ≤ n ≤ 50 000) — the number of messages in the
chronological log.
Each of the next n lines contains a message preceded by its author’s handle, a colon (‘:’) character, and
a space.
Each message is at most 139 characters long. Each handle is at most 20 characters long and does not
contain colons or spaces.
The input file contains only characters with ASCII codes between 32 and 126, inclusive, and line breaks.

Output

On the first line of the output file write the length of the longest conversation in the given log. On the
second line write 1-based indices of the messages in that conversation in ascending order.
If there are multiple longest conversations, write any one of them.

Sample Input

6
@Petr: Leaving for #NEERC tomorrow!
@Roman: This #NEERC is going to be awesome!
@Stone_in_forest: Nothing happened today.
@NEERCNews: @Petr Don’t forget an umbrella :)
@Lydia: @NEERCNews cares about @Petr - so cute ^ ^
@Lydia: @Lydia @NEERCNews @Petr it won’t be raining though!

Sample Output

3
1 4 5

  题意很简单,就是给你一堆社交网络上的状态,然后很好多人互相@,让你找一条最长的对话链,其中除了第一条对话,每一个人都@了链中说话的前一个人。

如果人名都是数字的话可以直接DP一下就过去了,问题是这边人名是字符串,所以得把字符串对应成数字才能DP啊...所以就很自然想到了用map<string,int>把字符串对应成数字。但是写完居然T了,很不能理解,觉得map已经不能更快了...后来查了一下发现,map的实现是依靠红黑树的二分实现,并不是我之前所想的哈希实现,真正哈希实现的是Hash_map。

               以前从来没用过hash_map,但感觉上用起来应该跟map差不多,由于是哈希实现的效率会比map快一个logn。引了一个库之后在本地编译过了,交上HDU返回CE,这说明hash_map确实不是C++标准的库里面的东西...在网上查了一些资料,把include部分改了不少终于交上去没问题了,因为Hash_map在不同编译环境下要引的包貌似不一样,具体看代码的头部。现在写的版本在HDU和BUAAOJ上都亲测可以编译通过。

              最后吐槽一下...用了Hash_map发现还是T才发现是有个地方写死循环了...但Mac的Xcode和Win的CB下运行都没问题所以就一直没发现。改了一行之后交上去发现用map其实也随意就过了TAT....不过至少知道了怎么引用Hash_map,而且从运行时间上看Hash_map的版本确实比map快了1倍左右,不知道真正比赛的环境能不能用上Hash_map。个人觉得应该没有题会卡到只有用Hash_map才能过吧....

            也收获了一个教训:要充分检查之后再相信是自己算法有问题,不能过度自信,也不能过度自我怀疑

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<stack>

#ifdef __GNUC__
#include <ext/hash_map>
#else
#include <hash_map>
#endif

#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <unordered_map>
#endif

namespace std
{
    using namespace __gnu_cxx;
}

namespace __gnu_cxx
{
    template<> struct hash< std::string >
    {
        size_t operator()( const std::string& x ) const{
            return hash< const char* >()(x.c_str());
            }
    };
}

using namespace std;

#define CLR(a,b) memset(a,b,sizeof(a))
typedef long long ll;

hash_map<string,int> M;
const int maxn = 50000+20;
int n;
int slen;
int lmax[maxn];
int pre[maxn];
int hao[maxn];
char tmp[maxn];
char str[maxn];
int ans[maxn];

string get_name(int &pos){
    while(str[pos]!='@' && pos < slen)pos++;
    if(pos == slen-1){
        pos++;
        return "";
    }
    int len = 0;
    while(str[pos]!=':' && str[pos]!=' ' && pos < slen){
        tmp[len++] = str[pos++];
    }
    tmp[len] = '\0';
    string name(tmp);
    return name;
}

int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    while(scanf("%d",&n)!=EOF){
        int tot = 0;
        M.clear();
        CLR(lmax,0);
        CLR(hao, 0);
        CLR(pre,-1);
        for(int i=0;i<n;i++){
            //cout<<i<<endl;
            scanf(" %[^\n]", str);
            slen = strlen(str);
            int pos = 0;
            string name = get_name(pos);
            int cm;
            if(M[name]==0){
                M[name] = ++tot;
                cm = tot;
                hao[cm] = i;
                lmax[cm] = 1;
            }
            cm = M[name];
            if(i==0){
            pre[i] = -1;
            lmax[cm] = 1;
            hao[cm] = i;
            continue;
            }
            int now = M[name];
                while(pos < slen-1){
                    string cur = get_name(pos);
                    if(cur.length() == 0)break;
                    if(cur!=name && M[cur]!=0){
                    int idx = M[cur];
                    if(lmax[idx]+1 > lmax[now]){
                    lmax[now] = lmax[idx] + 1;
                    pre[i] = hao[idx];
                    hao[now] = i;
                    }
                }
            }
        }
        int mii = 0;
        int flag = 0;
        for(int i=1;i<=tot;i++){
                if(lmax[i] > mii){
                mii = lmax[i];
                flag = i;
            }
        }
        flag = hao[flag];
        printf("%d\n",mii);
        int cnt = 0;
        while(flag!=-1){
            ans[cnt++] = flag+1;
            flag = pre[flag];
        }
        for(int i=cnt-1;i>=0;i--){
            if(i==0)printf("%d",ans[i]);
            else printf("%d ",ans[i]);
            }
            printf("\n");
    }
    return 0;
}


/*
6
@Petr: Leaving for #NEERC tomorrow!
@Roman: This #NEERC is going to be awesome!
@Stone_in_forest: Nothing happened today.
@NEERCNews: @Petr Don’t forget an umbrella :)
@Lydia: @NEERCNews cares about @Petr - so cute ^ ^
@Lydia: @Lydia @NEERCNews @Petr it won’t be raining though!

6
@Petr: Leaving for #NEERC tomorrow!@Lydia
@Roman: This #NEERC is going to be awesome!
@Stone_in_forest: Nothing happened today.
@NEERCNews: @Petr Don’t forget an umbrella :)
@Lydia: @NEERCNews cares about @Petr - so cute ^ ^
@Lydia: @Lydia @NEERCNews @Petr it won’t be raining though!

5
@A:@B
@B:@C @D
@C:@A @B
@D:@C @A
@E:@A @B
*/






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值