题目 | 概括 |
---|---|
词频统计 | 枚举 |
相似度计算 | STL工具(tranform()转换大小写)+ 模拟 |
化学方程式配平 | 大模拟+高斯消元 |
1、词频统计
在学习了文本处理后,小 P 对英语书中的 n 篇文章进行了初步整理。
具体来说,小 P 将所有的英文单词都转化为了整数编号。
假设这 n 篇文章中共出现了 m 个不同的单词,则把它们从 1 到 m 进行编号。
这样,每篇文章就简化为了一个整数序列,其中每个数都在 1 到 m 范围内。
现给出小 P 处理后的 n 篇文章,对于每个单词 i (1≤i≤m ),试统计:
单词 i 出现在了多少篇文章中? 单词 i 在全部文章中总共出现了几次? 输入格式 输入共 n+1 行。
输入的第一行包含两个正整数 n 和 m ,分别表示文章篇数和单词编号上限。
输入的第 i+1 行包含由空格分隔的若干整数,其中第一个整数 li 表示第 i 篇文章的长度(单词个数);接下来 li
个整数表示对应的整数序列,序列中每个整数均在 1 到 m 范围内,各对应原文中的一个单词。输出格式 输出共 m 行。
第 i 行输出由空格分隔的两个整数 xi 和 yi ,表示共有 xi 篇文章包含单词 i ,总计出现次数为 yi 。
数据范围 全部的测试数据满足 0<n,m≤100 ,且每篇文章至少包含一个单词、最多不超过 100 个单词(1≤li≤100 )。
输入样例:
4 3
5 1 2 3 2 1
1 1
3 2 2 2
2 3 2
输出样例:
2 3
3 6
2 2
样例解释 单词 2 在:
文章 1 中出现两次;
文章 3 中出现三次;
文章 4 中出现一次。
因此 x2=3,y2=6 。
思路:
较为简单,按照步骤对题目进行枚举即可
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N= 103;
//统计所有文章总共包含几个i,并且包含i的文章的个数
int a[N][N];
int lth[N];//记录长度数组
int ma[N];
int cnt,mark;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
cin>>lth[i];
for(int j=1;j<=lth[i];j++)
{
scanf("%d",&a[i][j]);
}
}
//开始统计个数,从单词编号入手
for(int i=1;i<=m;i++)
{
cnt=0;
bool flag=false;
mark=0;
for(int j=1;j<=n;j++)//枚举每一个数组
{
for(int k=1;k<=lth[j];k++)//枚举到每一个序列的最后一个
{
if(a[j][k]==i)
{
cnt++;
flag=true;
}
}
if(flag)
{
mark++;//记录出现此数的文章的篇数
flag=false;
}
}
cout<<mark<<" "<<cnt<<endl;
}
return 0;
}
2、相似度计算
两个集合的 Jaccard 相似度定义为:
Sim(A,B)=|A∩B|/|A∪B| 即交集的大小除以并集的大小。
当集合 A 和 B 完全相同时,Sim(A,B)=1 取得最大值;当二者交集为空时,Sim(A,B)=0 取得最小值。
除了进行简单的词频统计,小 P 还希望使用 Jaccard 相似度来评估两篇文章的相似性。
具体来说,每篇文章均由若干个英文单词组成,且英文单词仅包含“大小写英文字母”。
对于给定的两篇文章,小 P 首先需要提取出两者的单词集合 A 和 B ,即去掉各自重复的单词。
然后计算出:
|A∩B| ,即有多少个不同的单词同时出现在两篇文章中; |A∪B| ,即两篇文章一共包含了多少个不同的单词。
最后再将两者相除即可算出相似度。需要注意,在整个计算过程中应当忽略英文字母大小写的区别,比如 the、The 和 THE 三者都应被视作同一个单词。
试编写程序帮助小 P 完成前两步,计算出 |A∩B| 和 |A∪B| ;小 P 将亲自完成最后一步的除法运算。
输入格式 输入共三行。
输入的第一行包含两个正整数 n 和 m ,分别表示两篇文章的单词个数。
第二行包含空格分隔的 n 个单词,表示第一篇文章;
第三行包含空格分隔的 m 个单词,表示第二篇文章。
输出格式 输出共两行。
第一行输出一个整数 |A∩B| ,即有多少个不同的单词同时出现在两篇文章中;
第二行输出一个整数 |A∪B| ,即两篇文章一共包含了多少个不同的单词。
数据范围 全部的测试数据满足:1≤n,m≤104 且每个单词最多包含 10 个字母。
输入样例1: 3 2 The tHe thE the THE 输出样例1: 1 1 样例1解释 A=B=A∩B=A∪B= {the}
输入样例2: 9 7 Par les soirs bleus dete jirai dans les sentiers PICOTE PAR
LES BLES FOULER LHERBE MENUE 输出样例2: 2 13 样例2解释 A= {bleus, dans, dete,
jirai, les, par, sentiers, soirs}|A|=8 B= {bles, fouler, les, lherbe,
menue, par, picote}|B|=7 A∩B= {les, par}|A∩B|=2
输入样例3: 15 15
Thou that art now the worlds fresh ornament And only herald to the gaudy spring
Shall I compare thee to a summers day Thou art more lovely and more temperate
输出样例3: 4 24
思路:
由于不区分大小写,所以把所有的字母都统一转化为大写进行处理(用到transform函数来处理字符串)
string x;
cin>>x;
transform(x.begin(),x.end(),x.begin(),::toupper);
用set进行去重,这样就可以简单的处理数据
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N=1e4;
unordered_set<string>s1,s2;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
string x;
cin>>x;
transform(x.begin(),x.end(),x.begin(),::toupper);
s1.insert(x);
}
int cnt=0;
for(int i=1;i<=m;i++)
{
string x;
cin>>x;
transform(x.begin(),x.end(),x.begin(),::toupper);
s2.insert(x);
}
for(auto t:s1)
{
if(s2.find(t)!=s2.end())
{
cnt++;
}
}
int total=s1.size()+s2.size();
cout<<cnt<<endl<<total-cnt;
return 0;
}
3、化学方程式配平
思路:
很显然是一个高斯消元(题目也进行了提示),但在这之前要妥善处理好数据,以便于正确、方便的运用
对数据的处理,转化为矩阵的函数:
void getElement(string str, int &index, int in)
{
str = str + '#';
string ele = "";
int num = 0;
bool complete = false;
for (int i = 0; i < str.size(); i++)
{
char c = str[i];
if (c >= '0' && c <= '9')
{
complete = true;
num = num * 10 + c - '0';
}
else
{
if (complete)
{
if (elei.find(ele) != elei.end())
{
mat[elei[ele]][in] = num;
}
else
{
elei[ele] = index++;
mat[elei[ele]][in] = num;
}
ele = c;
num = 0;
complete = false;
}
else
{
ele = ele + c;
}
}
}
}
代码:
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 42;
double mat[N][N];
int n, m;
map<string, int> elei;
int index;
double eps = 1e-6;
void initMat()
{
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
mat[i][j] = 0;
}
void getElement(string str, int &index, int in)
{
str = str + '#';
string ele = "";
int num = 0;
bool complete = false;
for (int i = 0; i < str.size(); i++)
{
char c = str[i];
if (c >= '0' && c <= '9')
{
complete = true;
num = num * 10 + c - '0';
}
else
{
if (complete)
{
if (elei.find(ele) != elei.end())
{
mat[elei[ele]][in] = num;
}
else
{
elei[ele] = index++;
mat[elei[ele]][in] = num;
}
ele = c;
num = 0;
complete = false;
}
else
{
ele = ele + c;
}
}
}
}
void _swap(int a, int b)
{
double tmp;
for (int i = 0; i < m; i++)
{
tmp = mat[a][i];
mat[a][i] = mat[b][i];
mat[b][i] = tmp;
}
}
void _sub(int a, int b)
{
double magni = mat[a][b] / mat[b][b];
for (int i = b; i < m; i++)
{
mat[a][i] -= mat[b][i] * magni;
}
}
int main()
{
cin >> n;
while (n--)
{
cin >> m;
string str;
initMat();
elei.clear();
index = 0;
for (int i = 0; i < m; i++)
{
cin >> str;
getElement(str, index, i);
}
for (int i = 0; i < m; i++)
{
int j;
for (j = i; j < index; j++)
if (fabs(mat[j][i]) >= eps)
break;
if (j == index)
continue;
else if (j != i)
{
_swap(i, j); // swap i j
}
for (j = i + 1; j < index; j++)
{
if (fabs(mat[j][i]) >= eps)
{
_sub(j, i); // j line sub i
}
}
}
int k;
for (k = 0; k < index && k < m; k++)
if (fabs(mat[k][k]) <= eps)
break;
if (k < m)
cout << "Y" << endl;
else
cout << "N" << endl;
}
return 0;
}