用户的昵称【哈希】

题目大意:

题目链接:http://10.156.17.250/JudgeOnline/showproblem?problem_id=1453(学校局域网)
给出一些人的昵称,求每个昵称有多少人在使用。不区分大小写。


思路:

这道题,模拟都能过。。。
我用了字符串哈希,定义哈希函数为

num=(num+s[i].s[k1]k)%MOD

之后判断numhash里面是否存在,如果存在,那么就找到之前的位置,将s[w[i]].a++(原来的位置加一),然后排序,输出即可。
跑的好慢啊QWQ暴力比这都还快。
这里写图片描述
这里写图片描述


代码:

#include <cstdio>
#include <string>
#include <algorithm>
#include <iostream>
#define MOD 1000007
using namespace std;

int n,num,len,j,w[MOD+1];
string ha[MOD+1];

struct node 
{
    string s;  //昵称
    int a;  //这个昵称的个数
}s[MOD+1];

void change(int x)  //大写转小写
{
    for  (int i=0;i<len;i++)
     if (s[x].s[i]>='A'&&s[x].s[i]<='Z') s[x].s[i]-=('A'-'a');
}

bool cmp(node x,node y)
{
    return x.s<y.s;
}

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        cin>>s[i].s;
        len=s[i].s.size();
        change(i);  //转换
        num=0;
        for (int k=1;k<=s[i].s.size();k++)
         num=(num+s[i].s[k-1]*k)%MOD;  //hash函数(也许不够优美)
        num%=MOD;
        j=num%MOD;      
        while (ha[j]!=""&&ha[j]!=s[i].s)    
         j=(j+1)%MOD;  //hash
        if (ha[j]==s[i].s)  //有过这个昵称
        {
            s[w[j]].a++;  //原来昵称的位置加一
        }
        else 
        {
            ha[j]=s[i].s;  //储存
            s[i].a++;
            w[j]=i;  //保存位置
        }
    }
    sort(s+1,s+1+n,cmp);
    for (int i=1;i<=n;i++)
     if (s[i].a)  //有这个昵称
      cout<<s[i].s<<" "<<s[i].a<<"\n";
    return 0;
}   
posted @ 2018-08-17 08:37  全OI最菜  阅读(58)  评论(0编辑  收藏  举报