[STL]余弦定理

来源:互联网 发布:淘宝怎么上货 编辑:程序博客网 时间:2024/05/16 01:53

Problem C: 余弦定理

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 338  Solved: 76
[Submit][Status][Web Board]

Description

 小Q在埃森哲工作有一段时间了,他觉得自己在一个岗位山做的时间有点长, 所以刚刚换了一个team,是一个搞数据挖掘文本处理的team。在文本挖掘领域,经常要将文本抽象为一个向量,而计算两个文本的相似度就是计算这两个向量的夹角。

现在我们具体的介绍如何将两段文本向量化后求取相似度:
1. 首先统计每个文本中所有词出现的频度,对于["I", "like", "nice", "girls"],可以得到频度向量("I":1, "like":1, "nice":1, "girls":1)。类似的,对于["I", "like", "strong", "boys"],则可以得到频度向量("I":1, "like":1, "strong":1, "boys":1)。
2. 可以发现两个向量的值完全相同,但是其中所代表的含义完全不相同,所以我们还需要对两个向量做对齐操作,即对各自向量添加一些空项。则两个新向量为("I":1, "like":1, "nice":1, "girls":1, "strong":0, "boys":0)和("I":1, "like":1, "nice":0, "girls":0, "strong":1, "boys":1)。
3. 使用余弦定理对两个向量(1, 1, 1, 1, 0, 0)和(1, 1, 0, 0, 1, 1)求夹角,近似表示两个文本的近似度。
Sim(A, B) = (A[0]*B[0]+A[1]*B[1]+...+A[n]*B[n])/(sqrt(A[0]*A[0]+A[1]*A[1]+...+A[n]*A[n])*sqrt(B[0]*B[0]+B[1]*B[1]+...+B[n]*B[n]))。
现在给你两段文本A和B,希望你用如上所述的方法计算Sim(A, B)。

Input

 多组测试数据。每组数据两行。

第1行:输入一个文本A,文本由若干单词组成。
第2行: 输入一个文本B,文本由若干单词组成。
所有单词都只由英文大小写字母构成,相邻单词由一个空格隔开。

Output

 对于每组数据。输出一行,包含一个保留小数点后两位的浮点数,代表Sim(A, B)。

Sample Input

I like strong boysI like nice girls

Sample Output

0.50

HINT


输入比较困难,可以先读入一行到临时空间,再用sprintf或strstream来格式化。其余就比较简单了。

格式化版本:

#include <cmath>#include <cstdio>#include <iostream>#include <strstream>#include <map>using namespace std;inline int getint(){int res=0;char tmp;bool sgn=1;do tmp=getchar();while (!isdigit(tmp)&&tmp!='-');if (tmp=='-'){sgn=0;tmp=getchar();}do res=(res<<3)+(res<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?res:-res;}map<string,int> h1;map<string,int> h2;char word[10000000];bool work(map<string,int> &hash){string line;string word;strstream ss1;getline(cin,line);if (cin.eof()) return false;ss1 << line;while (!ss1.eof()){ss1 >> word;hash[word]++;}return true;}map<string,int>::iterator it1;map<string,int>::iterator it2;int main(){freopen("c.in","r",stdin);freopen("c.out","w",stdout);bool first = true;for (;;){h1.clear();h2.clear();if (!work(h1)) break;work(h2);if (!first)printf("\n");first = false;int fenzi = 0;int fenmu1 = 0;int fenmu2 = 0;string tmp;for (it1=h1.begin();it1!=h1.end();it1++){fenmu1 += it1->second*it1->second;}for (it1=h2.begin();it1!=h2.end();it1++){fenmu2 += it1->second*it1->second;}for (it1=h1.begin();it1!=h1.end();){tmp = it1->first;it2 = h2.find(tmp);if (it2!=h2.end()){fenzi += it1->second*it2->second;h2.erase(it2);}it2 = it1;it1 ++;h1.erase(it2);}for (it2=h2.begin();it2!=h2.end();){tmp = it2->first;it1 = h1.find(tmp);if (it1!=h1.end()){fenzi += it1->second*it2->second;h1.erase(it1);}it1 = it2;it2 ++;h2.erase(it1);}//printf("%.2f\n",sqrt(double(fenmu1)));printf("%.2f",double(fenzi)/(sqrt(double(fenmu1))*sqrt(double(fenmu2))));}return 0;}

手动处理版本:

#include <cmath>#include <cstdio>#include <string>#include <cstring>#include <iostream>#include <map>using namespace std;inline int getint(){    int res=0;char tmp;bool sgn=1;    do tmp=getchar();    while (!isdigit(tmp)&&tmp!='-');    if (tmp=='-'){sgn=0;tmp=getchar();}    do res=(res<<3)+(res<<1)+tmp-'0';    while (isdigit(tmp=getchar()));    return sgn?res:-res;}map<string,int> h1;map<string,int> h2;char word[10000000];bool work(map<string,int> &hash){    for(;;)    {        for (;;)        {            int tt = scanf("%[^\n ]",word);            if (tt == EOF)                return false;            if (tt == 0)                getchar();            else                break;        }        hash[string(word)] ++;        if (getchar() == '\n')            break;    }    return true;}map<string,int>::iterator it1;map<string,int>::iterator it2;int main(){    bool first = true;    for (;;)    {        h1.clear();        h2.clear();        if (!work(h1)) break;        work(h2);        if (!first)            printf("\n");        first = false;        int fenzi = 0;        int fenmu1 = 0;        int fenmu2 = 0;        string tmp;        for (it1=h1.begin();it1!=h1.end();it1++)        {            fenmu1 += it1->second*it1->second;        }        for (it1=h2.begin();it1!=h2.end();it1++)        {            fenmu2 += it1->second*it1->second;        }        for (it1=h1.begin();it1!=h1.end();)        {            tmp = it1->first;            it2 = h2.find(tmp);            if (it2!=h2.end())            {                fenzi += it1->second*it2->second;                h2.erase(it2);            }            it2 = it1;            it1 ++;            h1.erase(it2);        }        for (it2=h2.begin();it2!=h2.end();)        {            tmp = it2->first;            it1 = h1.find(tmp);            if (it1!=h1.end())            {                fenzi += it1->second*it2->second;                h1.erase(it1);            }            it1 = it2;            it2 ++;            h2.erase(it1);        }        //printf("%.2f\n",sqrt(double(fenmu1)));        printf("%.2f",double(fenzi)/(sqrt(double(fenmu1))*sqrt(double(fenmu2))));    }    return 0;}


0 0
原创粉丝点击