鱼C论坛

 找回密码
 立即注册
查看: 1617|回复: 9

[已解决]C++倒排索引表问题求解

[复制链接]
发表于 2021-11-15 21:19:29 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
3,实验要求
(1)输入格式说明:
输入首先给出正整数N(<=100),为文件总数。随后按以下格式给出每个文件的内容:首先给出文件正文,最后在一行中只给出一个字符“#”,表示文件结束。在N个文件内容结束之后,给出查询总数M(<=104),随后M行,每行给出一对文件编号,其间以空格分隔。这里假设文件按给出的顺序从1到N编号。
(2)输出格式说明:
针对每一条查询,在一行中输出两文件的相似度,即两文件的公共词汇量占两文件总词汇量的百分比,精确到小数点后1位。注意这里的一个“单词”只包括仅由英文字母组成的、
长度不小于3、且不超过10的英文单词,长度超过10的只考虑前10个字母。单词间以任何非英文字母隔开。另外,大小写不同的同一单词被认为是相同的单词,例如“You”和“you”是同一个单词。
3)样例输入与输出:
输入
3
Aaa Bbb Ccc
#
Bbb Ccc Ddd
#
Aaa2 ccc Eee
is at Ddd@Fff
#
2
1 2
1 3
输出
50.0%
33.3%

下面是我自己写的代码:
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. #include <iomanip>
  5. #include <algorithm>
  6. using namespace std;

  7. struct Document
  8. {
  9.         int docID;
  10.         vector<string> words;
  11. };

  12. class CompareFile
  13. {
  14. private:
  15.     vector<Document> collection;
  16.     int N,M;
  17.     string s;
  18. public:
  19.         void input()
  20.         {
  21.             cin>>N;
  22.             int i = 0;
  23.             string temp;
  24.             while(true)
  25.         {
  26.             getline(cin, temp);
  27.             s = s + temp;
  28.             if(temp[0] == '#') i++;
  29.             if(i == N)
  30.                 break;
  31.         }
  32.         for(i = 0; i < N; ++i)
  33.         {
  34.             collection[i].docID = i + 1;
  35.         }
  36.         }
  37.         bool EqualWords(string s1,string s2)
  38.         {
  39.             string::size_type i;
  40.             if(s1.size() != s2.size())
  41.             return false;
  42.         else
  43.         {
  44.             for(i = 0;i < s1.size(); ++i)
  45.             {
  46.                 if(s1[i] != s2[i] && s1[i] != s2[i] + 32 && s1[i] != s2[i] - 32)
  47.                     return false;
  48.             }
  49.         }
  50.         return true;
  51.         }
  52.     void indexDocument(int docID)
  53.     {
  54.         string::size_type n;
  55.         int i;
  56.         n = 0;
  57.         for(i = 0; i < docID - 1; ++i)
  58.         {
  59.             n = s.find("#",n);
  60.             n = n + 1;
  61.         }
  62.         string indexItem = "";
  63.         while(s[n] != '#')
  64.         {
  65.             //读取单词,给索引项赋值
  66.             while (isalpha(s[n]))
  67.             {
  68.                 indexItem += s[n];
  69.                 n++;
  70.             }
  71.             if(indexItem.size() < 3)
  72.                 continue;
  73.             if(indexItem.size() >= 10)
  74.                 indexItem = indexItem.substr(0,10);
  75.             //把索引项加入词典
  76.             collection[docID - 1].words.push_back(indexItem);
  77.             //清空索引项,准备下一次
  78.             indexItem = "";
  79.             n++;
  80.         }
  81.     }
  82.     void indexCollection()
  83.     {
  84.         //打开对应的文件并索引
  85.         for (int i = 0; i < N; i++)
  86.         {
  87.             //索引单篇文档
  88.             indexDocument(collection[i].docID);
  89.         }
  90.     }
  91.     static bool cmp(string a, string b)
  92.     {
  93.         return a < b;//词项按照从小到大排序
  94.     }
  95.     void sortIndex(Document doc)
  96.     {
  97.         sort(doc.words.begin(), doc.words.end(), cmp);
  98.     }
  99.     void mergeIndex()
  100.     {
  101.         int j;
  102.         for(j = 0; j < N; ++j)
  103.         {
  104.             sortIndex(collection[j]);
  105.         }
  106.         vector<string>::iterator it_cur;//创建迭代器
  107.         vector<string>::iterator it_next;
  108.         vector<Document>::iterator i = collection.begin();
  109.         while(i != collection.end())
  110.         {
  111.             it_cur = (*i).words.begin();
  112.             it_next = it_cur + 1;
  113.             while (it_cur != (*i).words.end())
  114.             {
  115.                 if(it_cur + 1 != (*i).words.end()) it_next = it_cur + 1;
  116.                 else break;
  117.                 while(EqualWords((*it_cur),(*it_next)))
  118.                 {//这个循环内处理掉所有与当前词项重复的词项
  119.                     (*i).words.erase(it_next);//删除重复项
  120.                     if (it_cur + 1 != (*i).words.end()) it_next = it_cur + 1;
  121.                     else break;
  122.                 }
  123.                 it_cur++;
  124.             }
  125.             i++;
  126.         }
  127.     }
  128.         void Compare(int docID1,int docID2)
  129.     {
  130.         int a = docID1 - 1 ,b = docID2 - 1;
  131.         int Count = 0,sum;
  132.         sum = collection[a].words.size() + collection[b].words.size();
  133.         vector<string>::iterator it_cur1;//创建迭代器
  134.         vector<string>::iterator it_cur2;
  135.         it_cur1 = collection[a].words.begin();
  136.         it_cur2 = collection[b].words.begin();
  137.         while(it_cur1 != collection[a].words.end())
  138.         {
  139.             while(it_cur2 != collection[b].words.end())
  140.             {
  141.                 if(EqualWords((*it_cur1),(*it_cur2)))
  142.                 {
  143.                     Count++;
  144.                     sum--;
  145.                     break;
  146.                 }
  147.                 it_cur2++;
  148.              }
  149.              it_cur1++;
  150.         }
  151.         double r = Count/sum * 100;
  152.         cout<<setiosflags(ios::fixed)<<setprecision(1)<<r<<"%"<<endl;
  153.     }
  154.     //~CompareFile();
  155. };

  156. int main()
  157. {
  158.     CompareFile t;
  159.     t.input();
  160.     t.indexCollection();
  161.     t.mergeIndex();
  162.     t.Compare(1,2);
  163.     //for(int i = 0;i < N;++i)
  164.     //   cout<<s[i];
  165.     //int a,b;
  166.     //cin>>a>>b;
  167.     //t.Compare(s,a,b);
  168.     return 0;
  169. }
复制代码

不知道为啥运行没反应
最佳答案
2021-11-17 16:16:29
本帖最后由 jhq999 于 2021-11-17 16:37 编辑
  1. #include <stdio.h>
  2. #include <iostream>
  3. #include <string>
  4. using namespace std;



  5. #define STRINGMAXSIZE 64
  6. int wordsum(string *instr,string *words=NULL,int count=0)//只输入一个参数时,返回字符串单词数量,否则分离出单词
  7. {
  8.         int i = 0;
  9.         int start=0;
  10.         if (NULL==words)
  11.         {

  12.                 for (i=0;instr->c_str()[i]; i++)
  13.                 {
  14.                         if (('a'>instr->c_str()[i]||'z'<instr->c_str()[i])&&('A'>instr->c_str()[i]||'Z'<instr->c_str()[i]))
  15.                         {
  16.                                 if (0x20!=instr->c_str()[i])
  17.                                 {
  18.                                         *instr=instr->replace(i,1," ");//把不是字母的都替换成空格

  19.                                 }
  20.                                 if (instr->substr(start,i-start).c_str()[0]&&(0x20!=instr->substr(start,i-start).c_str()[0]))//如果子字符串开头不是0和空格单词数量加一
  21.                                 {
  22.                                         count++;
  23.                                 }
  24.                                 start=i+1;
  25.                         }
  26.                 }
  27.                 return count;
  28.         }


  29.         else if (count)//分离出单词
  30.         {

  31.                 for (i=0;instr->c_str()[i]; i++)
  32.                 {
  33.                         if (0x20==instr->c_str()[i])
  34.                         {
  35.                                 if (instr->substr(start,i-start).c_str()[0]&&0x20!=instr->substr(start,i-start).c_str()[0])
  36.                                 {

  37.                                
  38.                                         words[--count]=instr->substr(start,i-start);
  39.                                         if (words[count].length()>10)//大于10的单词取10个字符
  40.                                         {
  41.                                                 words[count]=words[count].substr(0,10);
  42.                                         }
  43.                                 }
  44.                                 start=i+1;
  45.                         }
  46.                 }
  47.         }


  48.         return count;
  49. }
  50. double cmpword(string *words1,string *words2,int word1count,int word2count)
  51. {
  52.         double count=0;
  53.         bool flag=0;
  54.         for (int i = 0; i < word1count; i++)
  55.         {
  56.                 if (words1[i].length()<3)continue;//小于3丢掉
  57.                
  58.                 flag=0;
  59.                 for (int j = 0; j <word2count; j++)
  60.                 {
  61.                         if (words2[j].length()<3)continue;//小于3丢掉
  62.                         if (!_stricmp(words1[i].c_str(),words2[j].c_str()))//不区分大小写比对
  63.                         {
  64.                                 if (0==flag)
  65.                                 {
  66.                                         count++;
  67.                                         flag=1;
  68.                                 }
  69.                                 count++;
  70.                                 cout<<words1[i]<<endl;
  71.                         }
  72.                 }
  73.         }
  74.         return (count*100)/(double)(word1count+word2count);
  75. }
  76. int cmpstr(string *strs,int n,int (*team)[2],int m)
  77. {
  78.         int i=0,j=0,*wordcount=new int[n];
  79.         string **word=new string*[n];
  80.         for (i = 0; i < n; i++)
  81.         {
  82.                 wordcount[i]=wordsum(&strs[i]);
  83.                 word[i]=new string[wordcount[i]];
  84.                 wordsum(&strs[i],word[i],wordcount[i]);
  85.         }

  86.         for (i = 0; i < m; i++)
  87.         {
  88.                 //cout<<setprecision(1)<<cmpword(word[team[i][0]-1],word[team[i][1]-1],wordcount[team[i][0]-1],wordcount[team[i][1]-1])<<endl;
  89.                 printf("%.1lf%%\n",cmpword(word[team[i][0]-1],word[team[i][1]-1],wordcount[team[i][0]-1],wordcount[team[i][1]-1]));
  90.         }

  91.         for (i = 0; i < n; i++)
  92.         {
  93.                 delete[] word[i];
  94.         }
  95.         delete[] wordcount;
  96.         delete[] word;
  97.         return 0;
  98. }
  99. int main()
  100. {

  101.         int i=0,j=0,m=0,n=0;
  102.         cin>>n;
  103.         fflush(stdin);
  104.         string *strs=new string[n];
  105.         for (i = 0; i <n; i++)
  106.         {
  107.                 strs[i].resize(STRINGMAXSIZE);
  108.                 scanf("%[^#]",strs[i].data());
  109.                 fflush(stdin);
  110.         }
  111.         cin>>m;
  112.         fflush(stdin);
  113.         int (*team)[2]=(int(*)[2])(new int[2*m*4]);
  114.         for (i = 0; i < m; i++)
  115.         {
  116.                 cin>>team[i][0]>>team[i][1];
  117.         }
  118.         cmpstr(strs,n,team,m);
  119.         delete[] team;
  120.         delete[] strs;
  121.         return 0;
  122. }
复制代码
  1. 3
  2. Aaa Bbb Ccc ABCDEFGHIJ
  3. #
  4. Bbb Ccc Ddd
  5. #
  6. Aaa2  ccc Eee
  7. is at Ddd@Fff
  8. abcdefghijklmn
  9. #
  10. 3
  11. 1 2
  12. 1 3
  13. 2 3
  14. Ccc
  15. Bbb
  16. 57.1%
  17. ABCDEFGHIJ
  18. Ccc
  19. Aaa
  20. 50.0%
  21. Ddd
  22. Ccc
  23. 36.4%
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-11-15 21:27:17 | 显示全部楼层
这题很不错,有挑战性
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-16 13:14:04 | 显示全部楼层
傻眼貓咪 发表于 2021-11-15 21:27
这题很不错,有挑战性

做出来了吗哥
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-16 17:48:53 | 显示全部楼层

抱歉,我试了,但是不能,可能需要其他大佬看看了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-16 17:52:43 | 显示全部楼层

33.3% 是怎么算出来的?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-17 16:16:29 | 显示全部楼层    本楼为最佳答案   
本帖最后由 jhq999 于 2021-11-17 16:37 编辑
  1. #include <stdio.h>
  2. #include <iostream>
  3. #include <string>
  4. using namespace std;



  5. #define STRINGMAXSIZE 64
  6. int wordsum(string *instr,string *words=NULL,int count=0)//只输入一个参数时,返回字符串单词数量,否则分离出单词
  7. {
  8.         int i = 0;
  9.         int start=0;
  10.         if (NULL==words)
  11.         {

  12.                 for (i=0;instr->c_str()[i]; i++)
  13.                 {
  14.                         if (('a'>instr->c_str()[i]||'z'<instr->c_str()[i])&&('A'>instr->c_str()[i]||'Z'<instr->c_str()[i]))
  15.                         {
  16.                                 if (0x20!=instr->c_str()[i])
  17.                                 {
  18.                                         *instr=instr->replace(i,1," ");//把不是字母的都替换成空格

  19.                                 }
  20.                                 if (instr->substr(start,i-start).c_str()[0]&&(0x20!=instr->substr(start,i-start).c_str()[0]))//如果子字符串开头不是0和空格单词数量加一
  21.                                 {
  22.                                         count++;
  23.                                 }
  24.                                 start=i+1;
  25.                         }
  26.                 }
  27.                 return count;
  28.         }


  29.         else if (count)//分离出单词
  30.         {

  31.                 for (i=0;instr->c_str()[i]; i++)
  32.                 {
  33.                         if (0x20==instr->c_str()[i])
  34.                         {
  35.                                 if (instr->substr(start,i-start).c_str()[0]&&0x20!=instr->substr(start,i-start).c_str()[0])
  36.                                 {

  37.                                
  38.                                         words[--count]=instr->substr(start,i-start);
  39.                                         if (words[count].length()>10)//大于10的单词取10个字符
  40.                                         {
  41.                                                 words[count]=words[count].substr(0,10);
  42.                                         }
  43.                                 }
  44.                                 start=i+1;
  45.                         }
  46.                 }
  47.         }


  48.         return count;
  49. }
  50. double cmpword(string *words1,string *words2,int word1count,int word2count)
  51. {
  52.         double count=0;
  53.         bool flag=0;
  54.         for (int i = 0; i < word1count; i++)
  55.         {
  56.                 if (words1[i].length()<3)continue;//小于3丢掉
  57.                
  58.                 flag=0;
  59.                 for (int j = 0; j <word2count; j++)
  60.                 {
  61.                         if (words2[j].length()<3)continue;//小于3丢掉
  62.                         if (!_stricmp(words1[i].c_str(),words2[j].c_str()))//不区分大小写比对
  63.                         {
  64.                                 if (0==flag)
  65.                                 {
  66.                                         count++;
  67.                                         flag=1;
  68.                                 }
  69.                                 count++;
  70.                                 cout<<words1[i]<<endl;
  71.                         }
  72.                 }
  73.         }
  74.         return (count*100)/(double)(word1count+word2count);
  75. }
  76. int cmpstr(string *strs,int n,int (*team)[2],int m)
  77. {
  78.         int i=0,j=0,*wordcount=new int[n];
  79.         string **word=new string*[n];
  80.         for (i = 0; i < n; i++)
  81.         {
  82.                 wordcount[i]=wordsum(&strs[i]);
  83.                 word[i]=new string[wordcount[i]];
  84.                 wordsum(&strs[i],word[i],wordcount[i]);
  85.         }

  86.         for (i = 0; i < m; i++)
  87.         {
  88.                 //cout<<setprecision(1)<<cmpword(word[team[i][0]-1],word[team[i][1]-1],wordcount[team[i][0]-1],wordcount[team[i][1]-1])<<endl;
  89.                 printf("%.1lf%%\n",cmpword(word[team[i][0]-1],word[team[i][1]-1],wordcount[team[i][0]-1],wordcount[team[i][1]-1]));
  90.         }

  91.         for (i = 0; i < n; i++)
  92.         {
  93.                 delete[] word[i];
  94.         }
  95.         delete[] wordcount;
  96.         delete[] word;
  97.         return 0;
  98. }
  99. int main()
  100. {

  101.         int i=0,j=0,m=0,n=0;
  102.         cin>>n;
  103.         fflush(stdin);
  104.         string *strs=new string[n];
  105.         for (i = 0; i <n; i++)
  106.         {
  107.                 strs[i].resize(STRINGMAXSIZE);
  108.                 scanf("%[^#]",strs[i].data());
  109.                 fflush(stdin);
  110.         }
  111.         cin>>m;
  112.         fflush(stdin);
  113.         int (*team)[2]=(int(*)[2])(new int[2*m*4]);
  114.         for (i = 0; i < m; i++)
  115.         {
  116.                 cin>>team[i][0]>>team[i][1];
  117.         }
  118.         cmpstr(strs,n,team,m);
  119.         delete[] team;
  120.         delete[] strs;
  121.         return 0;
  122. }
复制代码
  1. 3
  2. Aaa Bbb Ccc ABCDEFGHIJ
  3. #
  4. Bbb Ccc Ddd
  5. #
  6. Aaa2  ccc Eee
  7. is at Ddd@Fff
  8. abcdefghijklmn
  9. #
  10. 3
  11. 1 2
  12. 1 3
  13. 2 3
  14. Ccc
  15. Bbb
  16. 57.1%
  17. ABCDEFGHIJ
  18. Ccc
  19. Aaa
  20. 50.0%
  21. Ddd
  22. Ccc
  23. 36.4%
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-21 19:02:59 | 显示全部楼层
人造人 发表于 2021-11-16 17:52
33.3% 是怎么算出来的?

一共有六个词(重复算一次),其中AAA,CCC重复,is和at长度不过二不算
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-21 19:03:59 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-21 19:08:04 | 显示全部楼层
Dogelike 发表于 2021-11-21 19:02
一共有六个词(重复算一次),其中AAA,CCC重复,is和at长度不过二不算

嗯,明白了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-21 19:34:25 | 显示全部楼层

大佬你的程序应该词数记错了,输出结果和我放的不一样
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-25 13:17

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表