5-46 新浪微博热门话题 (30分)

5-46 新浪微博热门话题 (30分)

新浪微博可以在发言中嵌入“话题”,即将发言中的话题文字写在一对“#”之间,就可以生成话题链接,点击链接可以看到有多少人在跟自己讨论相同或者相似的话题。新浪微博还会随时更新热门话题列表,并将最热门的话题放在醒目的位置推荐大家关注。

本题目要求实现一个简化的热门话题推荐功能,从大量英文(因为中文分词处理比较麻烦)微博中解析出话题,找出被最多条微博提到的话题。
输入格式:

输入说明:输入首先给出一个正整数N( 105 ≤ 10 5 ​​),随后N行,每行给出一条英文微博,其长度不超过140个字符。任何包含在一对最近的#中的内容均被认为是一个话题,如果长度超过40个字符,则只保留前40个字符。输入保证#成对出现。
输出格式:

第一行输出被最多条微博提到的话题,第二行输出其被提到的微博条数。如果这样的话题不唯一,则输出按字母序最小的话题,并在第三行输出And k more …,其中k是另外几条热门话题的条数。输入保证至少存在一条话题。
输入样例:

4
This is a #test of topic#.
Another #Test of topic.#
This is a #Hot# #Hot# topic
Another #hot!# #Hot# topic

输出样例:

Hot
2
And 1 more ...

思路
从测试案例来说,判断共同话题的时候应该是要忽略大小写、忽略标点符号的,可是,在输出的时后又要输出按字母序最小的话题,也就是说必须保留输入话题的原样(至少那个可能要被输出的话题要保留原样)。同5-44一般,我想试试哈希表,将每一个读入的话题放进去,对于相似话题直接合并并比较更新其为字母序最小的话题。
最后再做输出的时候就要遍历整个哈希表,找到题目要求的那些东西。
*需要验证的问题#PA#和#P A#算不算同一个话题
【180127】我理解错了。这道题没我想的那么复杂。他只要每读入一个话题,直接将话题格式化(转化为首字母大写,其他字母小写,除了数字都转化为空格,多个连续的空格自动合并成一个,前导后续空格也省略掉)。然后建一个双索引哈希散列(使用哈希散列是为了便于查找插入;另外使用一个数组是为了便于最后遍历话题统计信息时用)【其实一般包含哈希散列的C头文件、Java库之类的标准库所提供的散列函数本身就包含了这个功能】。

点击访问 PTA-测验

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MAXLENTH 1000007
/*提交时间  状态  分数  题目  编译器 耗时  用户
2018/1/27 14:12:56  答案正确    30  7-46    C (gcc) 195 ms  569985011
测试点 提示  结果  耗时  内存
0   sample 并列热门;同一微博重复提到的话题只算1次 答案正确    2 ms    144KB
1   一个话题    答案正确    2 ms    128KB
2   分词不同,算2个不同的话题;同一微博可包含多个话题   答案正确    1 ms    128KB
3   最大N;最长微博;最长话题   答案正确    195 ms  1168KB*/
typedef struct node *Node;
struct node {
    char* KTitle;//整理后的话题
    int Times;//提到次数
    int LastTimeWhoPost;//最近一次提及它的是哪条微博(用于去重)
};
void Scan(int);
int HashKey(char*);
int Mod(int);
void Insert(int,char*);

Node Hash[MAXLENTH];//散列存储
Node Titles[MAXLENTH]; // 建立双索引
int SumofTitles=0;//话题总数

int main() {
    int n;
    scanf("%d",&n);
    getchar();
    for(int i=0; i<n; i++) {
        Scan(i);
    }

    Node MostTimes=Titles[0];
    int NumofMost=0;
    for(int i=1; i<SumofTitles; i++) {
//      printf("{%s--%d}",Titles[i]->KTitle,Titles[i]->Times);
        if(Titles[i]->Times>MostTimes->Times) {
            MostTimes=Titles[i];
            NumofMost=0;
        } else if(Titles[i]->Times==MostTimes->Times) {
            if(strcmp(Titles[i]->KTitle,MostTimes->KTitle)<0) {
                MostTimes=Titles[i];
            }
            ++NumofMost;
        }
    }
    if(MostTimes->KTitle[0]>='a'&&MostTimes->KTitle[0]<='z')MostTimes->KTitle[0]+='A'-'a';
    printf("%s\n%d",MostTimes->KTitle,MostTimes->Times);
    if(NumofMost) {
        printf("\nAnd %d more ...",NumofMost);
    }
    return 0;
}
void Scan(int NumofWeibo) {
    char temp[141];//每行给出一条英文微博,其长度不超过140个字符
//  getchar();
    gets(temp);
    int Flag_Jin=0;
    char title[141];
    int Flag_Space=1;
//  printf("{S-%s}\n",temp);
    for(char*i=temp,*j=title; *i!='\0'; i++) {
        if(Flag_Jin==1) {
            switch(*i) {
                case '#':
                    while(*(j-1)==' ')--j;
                    *j='\0';
                    if(strlen(title)>0)//两个连续的#是空话题,不予计数 
                        Insert(NumofWeibo,title);
                    Flag_Jin=0;                 
                    j=title;
                    break;
                case 'a'...'z':
                case '0'...'9':
                    *j++=*i;
                    Flag_Space=0;
                    break;
                case 'A'...'Z':
                    *j++=*i-'A'+'a';
                    Flag_Space=0;
                    break;
                default:
                    if(Flag_Space==0) {
                        *j++=' ';
                        Flag_Space=1;
                    }
                    break;
            }
        } else if(*i=='#') {
            Flag_Jin=1;
            Flag_Space=1;
        }
    }
}
int HashKey(char*K) {
//  printf("&");
    unsigned int n=0;
    while(*K) {
        n+=*K-'a';
        n<<=5;
//      printf("(%d)",n);
        K++;
    }
//  printf("*-*");
    return n;
}
int Mod(int n) {
    while(n<0)n+=MAXLENTH;
    return n%MAXLENTH;
}
void Insert(int NumofWeibo,char*t) {//比较后插入散列表并更新话题原型
//  printf("{I-%s}",t);
    int Key=HashKey(t);
    int i=0,j=0;
    for( ; i<=MAXLENTH/2; i++) {
        j=Mod(Key+i);
        if(Hash[j]) {
            if(strcmp(t,Hash[j]->KTitle)==0) {
                if(Hash[j]->LastTimeWhoPost==NumofWeibo)return;
                ++Hash[j]->Times;
                Hash[j]->LastTimeWhoPost=NumofWeibo;
//              printf("{add:%s}",Hash[j]->KTitle);
            }
        } else break;
        j=Mod(Key-i);
        if(Hash[j]) {
            if(strcmp(t,Hash[j]->KTitle)==0) {
                if(Hash[j]->LastTimeWhoPost==NumofWeibo)return;
                ++Hash[j]->Times;
                Hash[j]->LastTimeWhoPost=NumofWeibo;
//              printf("{add:%s}",Hash[j]->KTitle);
            }
        } else break;
    }
    if(i>MAXLENTH/2) {
//      printf("NOT ENOUGH SPACE");
        exit(1);
    }
    Hash[j]=(Node)malloc(sizeof(struct node));
    Hash[j]->KTitle=(char*)malloc(strlen(t));
    strcpy(Hash[j]->KTitle,t);
    Hash[j]->Times=1;
    Hash[j]->LastTimeWhoPost=NumofWeibo;
    Titles[SumofTitles++]=Hash[j];//把新加入的元素在哈希表中的地址保存进数组。方便遍历。
//  printf("{new:%s}",Hash[j]->KTitle);
}
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值