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

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

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

输入格式:

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

输出格式:

第一行输出被最多条微博提到的话题,第二行输出其被提到的微博条数。如果这样的话题不唯一,则输出按字母序最小的话题,并在第三行输出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 ...

思路

  1. 读入话题
  2. 将话题规范化
  3. 建立两个表(一个表作为哈希表,另一个表用于顺序存储插入哈希表中的话题,以便于后续输出)
    1. 处理哈希冲突:开放地址法,即 Hi = (H(key) + di) % m,H(key)为散列函数,m为散列表长度,di为增量序列。

分析

  • 时间复杂度:O(1)
  • 空间复杂度:O(n)

运行结果

测试点提示结果耗时内存
0sample 并列热门;同一微博重复提到的话题只算1次答案正确3 ms384 KB
1一个话题答案正确3 ms296 KB
2分词不同,算2个不同的话题;同一微博可包含多个话题答案正确2 ms228 KB
3最大N;最长微博;最长话题答案正确141 ms768 KB

代码

#include <stdio.h>
#include <string.h>
#include <malloc.h>

#define MAXLENGTH   1000000 // 散列表大小,要保证装填因子小于一定阈值,否则会因频繁的哈希冲突而超时

typedef struct Node
{
    char *topic;            // 话题
    int count;              // 当前话题被提及的次数
    int last;               // 最后一次提及该话题的微博下标(用于去重)
}*Node;

Node hashTable[MAXLENGTH];  // 散列表
Node indices[MAXLENGTH];    // 将散列表紧凑化
int sumOfTopics;            // 话题总数

void solution();
void handle(char *text, int numberOfWeibo);     // 从文本中查找话题
void normalize(char *topic, int numberOfWeibo); // 将话题形式规范化
int hash(char *topic);                          // 计算散列值(可能越界)
int mod(int n);                                 // 对散列值取余
void insert(char *topic, int numberOfWeibo);    // 将话题插入到散列表

int main()
{
    solution();
    return 0;
}

void solution()
{
    int n;
    scanf("%d\n", &n);
    char buf[141];
    for (int i = 0; i < n; i++)
    {
        gets(buf);
        handle(buf, i);
    }
    Node maxTitle = indices[0];
    int num = 0;
    for (int i = 1; i < sumOfTopics; i++)
    {
        if (indices[i]->count > maxTitle->count)
        {
            maxTitle = indices[i];
            num = 0;
        }
        else if (indices[i]->count == maxTitle->count)
        {
            if (strcmp(indices[i]->topic, maxTitle->topic) < 0)
            {
                maxTitle = indices[i];
            }
            num++;
        }
    }
    if (maxTitle->topic[0] >= 'a' && maxTitle->topic[0] <= 'z') maxTitle->topic[0] -= 32;
    printf("%s\n%d\n", maxTitle->topic, maxTitle->count);
    if (num)
    {
        printf("And %d more ...\n", num);
    }
}

void handle(char *text, int numberOfWeibo)
{
    char *first;
    char *second;
    char buf[141];
    while ((first = strchr(text, '#')) != NULL && (second = strchr(first + 1, '#')) != NULL)
    {
        strncpy(buf, first + 1, second - first - 1);
        buf[second - first - 1] = '\0';
        normalize(buf, numberOfWeibo);
        text = second + 1;
    }
}

void normalize(char *topic, int numberOfWeibo)
{
    char *text = topic;
    if (!text || !*text) return;
    // 将非字母、数字的字符替换为空格
    while (*text)
    {
        if (*text >= 'A' && *text <= 'Z') *text += 32;
        else if (!(*text >= 'a' && *text <= 'z') && !(*text >= '0' && *text <= '9')) *text = ' ';
        text++;
    }

    char *first = NULL;
    char *second = NULL;
    char *rear = topic + strlen(topic);
    // 头部去空格
    text = topic;
    while (*text == ' ') text++;
    memmove(topic, text, rear - text + 1);
    rear -= text - topic;
    text = topic;
    // 中间和尾部去空格
    for (; *text; text++)
    {
        if (*text == ' ')
        {
            first = second = text;
            while (*second == ' ') second++;
            if (second - first != 1 && second != rear)
            {
                memmove(first + 1, second, rear - second + 1);
                rear -= second - first - 1;
            }
            else if(second == rear)
            {
                *first = '\0';
            }
        }
    }
    // 将话题插入散列表中
    insert(topic, numberOfWeibo);
}

int hash(char *topic)
{
    unsigned n = 0;
    while (*topic)
    {
        n += *topic - 'a';
        n <<= 5;
        topic++;
    }
    return n;
}

int mod(int n)
{
    while (n < 0) n += MAXLENGTH;
    return n % MAXLENGTH;
}

void insert(char *topic, int numberOfWeibo)
{
    int key = hash(topic);
    int i = 0;
    int j = 0;
    // 从中间往两侧探测,处理哈希冲突,找空位
    for (; i < MAXLENGTH / 2; i++)
    {
        j = mod(key + i); // 往右侧查找
        if (hashTable[j])
        {
            if (!strcmp(topic, hashTable[j]->topic))
            {
                if (hashTable[j]->last == numberOfWeibo) return;
                ++hashTable[j]->count;
                hashTable[j]->last = numberOfWeibo;
            }
        }
        else break;
        j = mod(key - i); // 往左侧查找
        if (hashTable[j])
        {
            if (!strcmp(topic, hashTable[j]->topic))
            {
                if (hashTable[j]->last == numberOfWeibo) return;
                ++hashTable[j]->count;
                hashTable[j]->last = numberOfWeibo;
            }
        }
        else break;
    }
    // 找到空位后,将新的结点插入到散列表中
    hashTable[j] = (Node)malloc(sizeof(struct Node));
    hashTable[j]->topic = (char*)malloc(strlen(topic) + 1);
    strcpy(hashTable[j]->topic, topic);
    hashTable[j]->count = 1;
    hashTable[j]->last = numberOfWeibo;
    indices[sumOfTopics++] = hashTable[j];
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我知道你想了解如何用 Python 爬取新浪微博评论。以下是一些步骤供您参考: 1. 安装必要的库 在使用 Python 爬取微博评论前,您需要安装一些必要的库。其中,requests 和 BeautifulSoup 库是必不可少的。 您可以使用以下命令在终端中安装它们: ``` pip install requests pip install beautifulsoup4 ``` 2. 登录微博并获取 cookie 在爬取微博评论之前,您需要登录您的微博账号并获取 cookie。 您可以使用 Chrome 浏览器登录您的微博账号。然后,按 F12 打开开发者工具,切换到“Network”选项卡并刷新页面。在“Filter”栏中输入“comment”,然后点击“XHR”选项卡。 接下来,您可以在“Headers”选项卡中找到“Request Headers”部,复制“Cookie”字段的值。 3. 构造请求 URL 在获取 cookie 后,您需要构造请求 URL。以下是一个示例 URL:https://weibo.cn/comment/Jf3bhk1V5?uid=123456&page=1 其中,Jf3bhk1V5 是微博的 ID,123456 是用户的 ID,page 是评论的页数。 您可以使用 requests 库发送 GET 请求并传递 cookie、微博 ID 和页数参数。 以下是一个示例代码: ``` import requests from bs4 import BeautifulSoup cookie = 'your_cookie_here' url = 'https://weibo.cn/comment/Jf3bhk1V5?uid=123456&page=1' headers = { 'Cookie': cookie } response = requests.get(url, headers=headers) soup = BeautifulSoup(response.text, 'html.parser') # 解析评论 ``` 4. 解析评论 最后,您需要解析页面上的评论。您可以使用 BeautifulSoup 库来解析 HTML。 以下是一个示例代码: ``` comments = soup.find_all('div', class_='c') for comment in comments: # 获取评论内容 content = comment.find('span', class_='ctt').text # 获取评论时间 time = comment.find('span', class_='ct').text # 获取评论用户 user = comment.find('a', class_='nk').text # 输出评论信息 print(f'{user}({time}): {content}\n') ``` 以上就是用 Python 爬取新浪微博评论的一些步骤。请注意,爬取微博评论可能会违反微博的使用协议,因此请谨慎使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值