PTA 数据结构与算法 7-46 新浪微博热门话题

如有不对,不吝赐教
这个题因为我看错了题目,结果多找了两天的bug,最后是对着别人的C++自己去找输出才找出来的……进入正题:

新浪微博可以在发言中嵌入“话题”,即将发言中的话题文字写在一对“#”之间,就可以生成话题链接,点击链接可以看到有多少人在跟自己讨论相同或者相似的话题。新浪微博还会随时更新热门话题列表,并将最热门的话题放在醒目的位置推荐大家关注。
本题目要求实现一个简化的热门话题推荐功能,从大量英文(因为中文分词处理比较麻烦)微博中解析出话题,找出被最多条微博提到的话题。

输入格式:
输入说明:输入首先给出一个正整数N(≤10^5​​),随后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.k的意义:

其中k是另外几条热门话题的条数

这里的k是热门话题,就是次数相同的话题条数-1(减去的1是自己)

2.同一条的相同话题算一条话题:

第一行输出被最多条微博提到的话题,第二行输出其被提到的微博条数

计算的是被微博提到的条数

3.最后的表述问题:

两条话题被认为是相同的,如果在去掉所有非英文字母和数字的符号、并忽略大小写区别后,
它们是相同的字符串;同时它们有完全相同的分词。输出时除首字母大写外,只保留小写英文
字母和数字,并用一个空格分隔原文中的单词。

那么问题来了,按照它的表述,#topic#和#topi1c#算同一条,那么输出的时候到底是输出#topic#还是#topi1c#呢?
根据我通过的代码和别人的代码,这两个东西不能算作一个话题,这就解决了。

这个题目中,我是用树结构来存话题的,然后在每次加入话题的时候比对这句话中的其他话题(用链表比对),最后在遍历一遍树的到k more,然后注意的一点就是输入字符串的处理。自己检查时最好多试试带特殊字符的,有前导后缀空格、特殊字符的以及一个句子有相同话题的,还有出现次数相同的话题的选取,如果都过了,基本上就没啥问题了。

下面给代码:

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

struct HotTopic{
char key[141];  //微博关键词
int count;        //该关键词出现的次数
struct HotTopic *left,*right;
};

struct TopicList{
char key[141];
struct TopicList *next;
};                 //用于在同一个微博中检验不同的话题

struct HotTopic *GetKey(struct HotTopic *root,char *weiBo,char *key);
struct HotTopic *InsertHT(struct HotTopic *root,char *key);
int InsertTL(struct TopicList **head,char *key);
void FreeHT(struct HotTopic *root);
void FreeTL(struct TopicList *head);

char hotKey[141];    //记录最火热关键词
int count=1;        //最热门话题数记录出现的次数
int all=0;          //记录热门话题总数
                    //这两个初始值定为1是因为总有一条话题
int main(void)
{
    int N;       //输入的微博
    int i;
    char weiBo[141];
    char key[141];
    struct HotTopic *root=(struct HotTopic *)malloc(sizeof(struct HotTopic));
    root->left=root->right=NULL;
    root->count=1;
    root->key[0]='\0';

    fscanf(stdin,"%d",&N);
    fgetc(stdin);

    for(i=0;i<N;i++){
      fgets(weiBo,141,stdin);
      root=GetKey(root,weiBo,key);        //获取关键词   并插入
    }

    printf("%s\n%d\n",hotKey,count);

    if(all)
      printf("And %d more ...\n",all);

    FreeHT(root);

    return 0;
}

struct HotTopic *GetKey(struct HotTopic *root,char *weiBo,char *key)
{
    int i,j;
    int flag;
    int tag;
    struct TopicList *head;

    head=NULL;
    i=0;

    while('\n'!=weiBo[i]&&weiBo[i]){
      j=0;
      tag=1;
      while('#'!=weiBo[i]&&'\n'!=weiBo[i]&&weiBo[i])
        i++;        //找到热门话题的开始
      if('\n'==weiBo[i]||!weiBo[i])
        break;                       //字符串结束

      i++;                           //略过'#'
      if(tag){
        while(!((weiBo[i]>='a'&&weiBo[i]<='z')||(weiBo[i]>='A'&&weiBo[i]<='Z')||(weiBo[i]>='0'&&weiBo[i]<='9')))
          i++;
        tag=0;
      }          //去掉前导空格

      while('#'!=weiBo[i]){
        flag=(weiBo[i]>='a'&&weiBo[i]<='z')||(weiBo[i]>='A'&&weiBo[i]<='Z')||(weiBo[i]>='0'&&weiBo[i]<='9');
        if(!flag){
          while(!flag&&'#'!=weiBo[i]){
            i++;
            flag=(weiBo[i]>='a'&&weiBo[i]<='z')||(weiBo[i]>='A'&&weiBo[i]<='Z')||(weiBo[i]>='0'&&weiBo[i]<='9');
          }
          if('#'==weiBo[i])
            break;
          key[j++]=' ';
        }                //把连续的特殊字符替换为一个空格
        key[j]=weiBo[i];
        if(key[j]>='A'&&key[j]<='Z')    //把大写字母改写成小写字母
          key[j]=key[j]-'A'+'a';
        j++;
        i++;
      }
      key[j]='\0';
      i++;
      if(key[0]<='z'&&key[0]>='a')
        key[0]=key[0]-'a'+'A';      //修改首字母

      if(InsertTL(&head,key))    //插入成功则说明第一次出现该热点话题
        root=InsertHT(root,key);
    }

    FreeTL(head);

    return root;
}

struct HotTopic *InsertHT(struct HotTopic *root,char *key)
{
    struct HotTopic *cur=root;
    struct HotTopic *newOne;

    newOne=(struct HotTopic *)malloc(sizeof(struct HotTopic));
    strcpy(newOne->key,key);
    newOne->count=1;
    newOne->left=newOne->right=NULL;

    if(!root->key[0]){
      root=newOne;
      strcpy(hotKey,key);
      return root;
    }              //只有第一个节点有

    while(strcmp(cur->key,key)){
      while(cur->left&&strcmp(cur->key,key)>0)
        cur=cur->left;
      if(strcmp(cur->key,key)>0){
        cur->left=newOne;
        break;
      }
      while(cur->right&&strcmp(cur->key,key)<0)
        cur=cur->right;
      if(strcmp(cur->key,key)<0){
        cur->right=newOne;
        break;
      }
    }

    if(!strcmp(cur->key,key)){
      cur->count++;
      if(count<cur->count||(count==cur->count&&strcmp(hotKey,cur->key)>0)){
        if(count>cur->count)
          all=1;
        if(count==cur->count)
          all++;
        strcpy(hotKey,cur->key);
        count=cur->count;
      }
      free(newOne);
      newOne=NULL;
    }

    return root;
}

int InsertTL(struct TopicList **head,char *key)
{
    struct TopicList *cur=*head;
    struct TopicList *newOne=(struct TopicList *)malloc(sizeof(struct TopicList));
    strcpy(newOne->key,key);
    newOne->next=NULL;

    if(!cur){
      *head=newOne;
      return 1;
    }

    if(!strcmp(cur->key,key)){
      free(newOne);
      newOne=NULL;
      return 0;
    }

    while(cur->next){
      if(strcmp(cur->next->key,key)>=0)
        break;
      cur=cur->next;
    }

    if(!cur->next){
      cur->next=newOne;
      return 1;
    }        //说明不存在该热词
    else if(strcmp(cur->next->key,key)>0){
      newOne->next=cur->next;
      cur->next=newOne;
      return 1;
    }
    else
      return 0;      //表示已经存在该话题
}

void FreeHT(struct HotTopic *root)
{
    if(!root)
      return ;

    if(root->left)
      FreeHT(root->left);
    if(root->right)
      FreeHT(root->right);

    free(root);
    root=NULL;

    return ;
}

void FreeTL(struct TopicList *head)
{
    if(!head)
      return ;

    struct TopicList *cur=head->next;

    while(cur){
      head->next=cur->next;
      free(cur);
      cur=NULL;
      cur=head->next;
    }

    free(head);
    head=NULL;

    return ;
}

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值