Dogelike 发表于 2021-11-15 21:19:29

C++倒排索引表问题求解

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%

下面是我自己写的代码:
#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <algorithm>
using namespace std;

struct Document
{
        int docID;
        vector<string> words;
};

class CompareFile
{
private:
    vector<Document> collection;
    int N,M;
    string s;
public:
        void input()
        {
          cin>>N;
          int i = 0;
          string temp;
          while(true)
      {
            getline(cin, temp);
            s = s + temp;
            if(temp == '#') i++;
            if(i == N)
                break;
      }
      for(i = 0; i < N; ++i)
      {
            collection.docID = i + 1;
      }
        }
        bool EqualWords(string s1,string s2)
        {
          string::size_type i;
          if(s1.size() != s2.size())
            return false;
      else
      {
            for(i = 0;i < s1.size(); ++i)
            {
                if(s1 != s2 && s1 != s2 + 32 && s1 != s2 - 32)
                  return false;
            }
      }
      return true;
        }
    void indexDocument(int docID)
    {
      string::size_type n;
      int i;
      n = 0;
      for(i = 0; i < docID - 1; ++i)
      {
            n = s.find("#",n);
            n = n + 1;
      }
      string indexItem = "";
      while(s != '#')
      {
            //读取单词,给索引项赋值
            while (isalpha(s))
            {
                indexItem += s;
                n++;
            }
            if(indexItem.size() < 3)
                continue;
            if(indexItem.size() >= 10)
                indexItem = indexItem.substr(0,10);
            //把索引项加入词典
            collection.words.push_back(indexItem);
            //清空索引项,准备下一次
            indexItem = "";
            n++;
      }
    }
    void indexCollection()
    {
      //打开对应的文件并索引
      for (int i = 0; i < N; i++)
      {
            //索引单篇文档
            indexDocument(collection.docID);
      }
    }
    static bool cmp(string a, string b)
    {
      return a < b;//词项按照从小到大排序
    }
    void sortIndex(Document doc)
    {
      sort(doc.words.begin(), doc.words.end(), cmp);
    }
    void mergeIndex()
    {
      int j;
      for(j = 0; j < N; ++j)
      {
            sortIndex(collection);
      }
      vector<string>::iterator it_cur;//创建迭代器
      vector<string>::iterator it_next;
      vector<Document>::iterator i = collection.begin();
      while(i != collection.end())
      {
            it_cur = (*i).words.begin();
            it_next = it_cur + 1;
            while (it_cur != (*i).words.end())
            {
                if(it_cur + 1 != (*i).words.end()) it_next = it_cur + 1;
                else break;
                while(EqualWords((*it_cur),(*it_next)))
                {//这个循环内处理掉所有与当前词项重复的词项
                  (*i).words.erase(it_next);//删除重复项
                  if (it_cur + 1 != (*i).words.end()) it_next = it_cur + 1;
                  else break;
                }
                it_cur++;
            }
            i++;
      }
    }
        void Compare(int docID1,int docID2)
    {
      int a = docID1 - 1 ,b = docID2 - 1;
      int Count = 0,sum;
      sum = collection.words.size() + collection.words.size();
      vector<string>::iterator it_cur1;//创建迭代器
      vector<string>::iterator it_cur2;
      it_cur1 = collection.words.begin();
      it_cur2 = collection.words.begin();
      while(it_cur1 != collection.words.end())
      {
            while(it_cur2 != collection.words.end())
            {
                if(EqualWords((*it_cur1),(*it_cur2)))
                {
                  Count++;
                  sum--;
                  break;
                }
                it_cur2++;
             }
             it_cur1++;
      }
      double r = Count/sum * 100;
      cout<<setiosflags(ios::fixed)<<setprecision(1)<<r<<"%"<<endl;
    }
    //~CompareFile();
};

int main()
{
    CompareFile t;
    t.input();
    t.indexCollection();
    t.mergeIndex();
    t.Compare(1,2);
    //for(int i = 0;i < N;++i)
    //   cout<<s;
    //int a,b;
    //cin>>a>>b;
    //t.Compare(s,a,b);
    return 0;
}
不知道为啥运行没反应

傻眼貓咪 发表于 2021-11-15 21:27:17

这题很不错,有挑战性

Dogelike 发表于 2021-11-16 13:14:04

傻眼貓咪 发表于 2021-11-15 21:27
这题很不错,有挑战性

做出来了吗哥

傻眼貓咪 发表于 2021-11-16 17:48:53

Dogelike 发表于 2021-11-16 13:14
做出来了吗哥

抱歉,我试了,但是不能,可能需要其他大佬看看了{:5_99:}

人造人 发表于 2021-11-16 17:52:43

Dogelike 发表于 2021-11-16 13:14
做出来了吗哥

33.3% 是怎么算出来的?

jhq999 发表于 2021-11-17 16:16:29

本帖最后由 jhq999 于 2021-11-17 16:37 编辑

#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;



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

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

                                }
                                if (instr->substr(start,i-start).c_str()&&(0x20!=instr->substr(start,i-start).c_str()))//如果子字符串开头不是0和空格单词数量加一
                                {
                                        count++;
                                }
                                start=i+1;
                        }
                }
                return count;
        }


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

                for (i=0;instr->c_str(); i++)
                {
                        if (0x20==instr->c_str())
                        {
                                if (instr->substr(start,i-start).c_str()&&0x20!=instr->substr(start,i-start).c_str())
                                {

                               
                                        words[--count]=instr->substr(start,i-start);
                                        if (words.length()>10)//大于10的单词取10个字符
                                        {
                                                words=words.substr(0,10);
                                        }
                                }
                                start=i+1;
                        }
                }
        }


        return count;
}
double cmpword(string *words1,string *words2,int word1count,int word2count)
{
        double count=0;
        bool flag=0;
        for (int i = 0; i < word1count; i++)
        {
                if (words1.length()<3)continue;//小于3丢掉
               
                flag=0;
                for (int j = 0; j <word2count; j++)
                {
                        if (words2.length()<3)continue;//小于3丢掉
                        if (!_stricmp(words1.c_str(),words2.c_str()))//不区分大小写比对
                        {
                                if (0==flag)
                                {
                                        count++;
                                        flag=1;
                                }
                                count++;
                                cout<<words1<<endl;
                        }
                }
        }
        return (count*100)/(double)(word1count+word2count);
}
int cmpstr(string *strs,int n,int (*team),int m)
{
        int i=0,j=0,*wordcount=new int;
        string **word=new string*;
        for (i = 0; i < n; i++)
        {
                wordcount=wordsum(&strs);
                word=new string];
                wordsum(&strs,word,wordcount);
        }

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

        for (i = 0; i < n; i++)
        {
                delete[] word;
        }
        delete[] wordcount;
        delete[] word;
        return 0;
}
int main()
{

        int i=0,j=0,m=0,n=0;
        cin>>n;
        fflush(stdin);
        string *strs=new string;
        for (i = 0; i <n; i++)
        {
                strs.resize(STRINGMAXSIZE);
                scanf("%[^#]",strs.data());
                fflush(stdin);
        }
        cin>>m;
        fflush(stdin);
        int (*team)=(int(*))(new int);
        for (i = 0; i < m; i++)
        {
                cin>>team>>team;
        }
        cmpstr(strs,n,team,m);
        delete[] team;
        delete[] strs;
        return 0;
}
3
Aaa Bbb Ccc ABCDEFGHIJ
#
Bbb Ccc Ddd
#
Aaa2ccc Eee
is at Ddd@Fff
abcdefghijklmn
#
3
1 2
1 3
2 3
Ccc
Bbb
57.1%
ABCDEFGHIJ
Ccc
Aaa
50.0%
Ddd
Ccc
36.4%

Dogelike 发表于 2021-11-21 19:02:59

人造人 发表于 2021-11-16 17:52
33.3% 是怎么算出来的?

一共有六个词(重复算一次),其中AAA,CCC重复,is和at长度不过二不算

Dogelike 发表于 2021-11-21 19:03:59

jhq999 发表于 2021-11-17 16:16


牛哇大佬

人造人 发表于 2021-11-21 19:08:04

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

嗯,明白了

Dogelike 发表于 2021-11-21 19:34:25

jhq999 发表于 2021-11-17 16:16


大佬你的程序应该词数记错了,输出结果和我放的不一样
页: [1]
查看完整版本: C++倒排索引表问题求解