原题链接:http://codeforces.com/gym/100338/attachments/download/2136/20062007-winter-petrozavodsk-camp-andrew-stankevich-contest-22-asc-22-en.pdf

题意

这是一个过滤垃圾邮件的算法,叫贝叶斯算法。这个算法的第一步是训练过程,通过人工给定的邮件,来确定每个词语在垃圾邮件中的概率和在普通邮件的概率。然后通过贝叶斯公式来计算每个邮件是否为垃圾邮件。具体过程可以看题,或者维基百科。

题解

模拟题目的过程即可,不过要注意的是,为了避免超时,必须哈希,使用 最小表示来记录字符串。

代码

//#include<iostream>
#include<cstring>
#include<fstream>
#include<vector>
#include<map>
#include<algorithm>
#include<string>
#include<set>
#include<cmath>
#include<queue>
#define eps 1e-10
#define MAX_N 1234
#define Pr 131
#define mod 1000000009
using namespace std; typedef long long ll; int s,g,n,t;
string sp[MAX_N];
string go[MAX_N];
string ma[MAX_N]; set<ll> spam[MAX_N];
set<ll> good[MAX_N];
set<ll> mail[MAX_N]; set<ll> allWord; string bankLine; map<ll, double> wordIsSpam;
map<ll, double> wordIsGood; double pSpam;
double pGood; ll Hash(string ss) {
ll tmp = Pr;
ll res = ;
for (auto c:ss) {
res = (res + c * tmp) % mod;
tmp = (tmp * Pr) % mod;
}
return res;
} string changeToSmall(string ss) {
string res = "";
for (auto c:ss) {
if (c <= 'Z' && c >= 'A')c = c - 'A' + 'a';
res = res + c;
}
return res;
} bool isAl(char c) {
if (c <= 'Z' && c >= 'A')return true;
return (c <= 'z' && 'a' <= c);
} void divi(string v[],set<ll> G[],int x) {
for (int i = ; i < x; i++) {
int p = ;
while ((!isAl(v[i][p])) && p < v[i].length())p++;
bool flag = true;
for (int j = p; j < v[i].length(); j++) {
if ((!isAl(v[i][j])) && flag) {
flag = false;
string tmp;
tmp.assign(v[i].begin() + p, v[i].begin() + j);
tmp = changeToSmall(tmp);
allWord.insert(Hash(tmp));
G[i].insert(Hash(tmp));
}
else if (isAl(v[i][j]) && flag == false) {
p = j;
flag = true;
}
}
}
} double divide(double a,double b) {
if (fabs(b)<eps)return ;
return a / b;
} double P(ll word) {
double ws, wg; if (wordIsSpam.find(word) == wordIsSpam.end())ws = ;
else ws = wordIsSpam[word]; if (wordIsGood.find(word) == wordIsGood.end())wg = ;
else wg = wordIsGood[word]; return divide(ws * pSpam, ws * pSpam + wg * pGood);
} int main() {
ifstream cin("spam.in");
ofstream cout("spam.out");
cin.sync_with_stdio(false);
cin >> s >> g >> n >> t;
pSpam = divide(s, s + g);
pGood = divide(g, s + g);
getline(cin, bankLine);
for (int i = ; i < s; i++) {
getline(cin, sp[i]);
sp[i] = sp[i] + " ";
}
for (int i = ; i < g; i++) {
getline(cin, go[i]);
go[i] = go[i] + " ";
}
for (int i = ; i < n; i++) {
getline(cin, ma[i]);
ma[i] = ma[i] + " ";
}
divi(sp, spam, s);
divi(go, good, g);
divi(ma, mail, n); for (auto word:allWord) {
int cnt = ;
for (int i = ; i < s; i++)
if (spam[i].find(word) != spam[i].end())cnt++;
wordIsSpam[word] = divide(cnt, s);
cnt = ;
for (int i = ; i < g; i++)
if (good[i].find(word) != good[i].end())cnt++;
wordIsGood[word] = divide(cnt, g);
}
for (int i = ; i < n; i++) {
double ans = ;
for (auto word:mail[i]) {
double p = P(word);
//cout<<word<<": "<<p<<endl;
if (p > 0.5 || fabs(p - 0.5) < eps)ans++;
}
if (ans * / mail[i].size() < t)cout << "good" << endl;
else cout << "spam" << endl;
}
return ;
}

Codeforces Gym 100338B Spam Filter 字符串哈希+贝叶斯公式的更多相关文章

  1. codeforces Gym 100338F Spam Filter 垃圾邮件过滤器(模拟,实现)

    阅读题, 概要:给出垃圾邮件和非垃圾邮件的集合,然后按照题目给出的贝叶斯公式计算概率一封邮件是垃圾邮件的概率. 逐个单词判断,将公式化简一下就是在垃圾邮件中出现的次数和在总次数的比值,大于二分之一就算 ...

  2. 【CodeForces】961 F. k-substrings 字符串哈希+二分

    [题目]F. k-substrings [题意]给定长度为n的串S,对于S的每个k-子串$s_ks_{k+1}...s_{n-k+1},k\in[1,\left \lceil \frac{n}{2} ...

  3. codeforces gym 100286 I iSharp (字符串模拟)

    题目链接 给定一个字符串.输入是int& a*[]&, b, c*; 输出是 int&&[]* a;int& b;int&* c; 输入格式里逗号后面一 ...

  4. codeforces gym 101164 K Cutting 字符串hash

    题意:给你两个字符串a,b,不区分大小写,将b分成三段,重新拼接,问是否能得到A: 思路:暴力枚举两个断点,然后check的时候需要字符串hash,O(1)复杂度N*N: 题目链接:传送门 #prag ...

  5. Codeforces Gym 100338B Geometry Problem 计算几何

    Problem B. Geometry ProblemTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudg ...

  6. Codeforces Round #543 (Div. 2) F dp + 二分 + 字符串哈希

    https://codeforces.com/contest/1121/problem/F 题意 给你一个有n(<=5000)个字符的串,有两种压缩字符的方法: 1. 压缩单一字符,代价为a 2 ...

  7. CodeForces Gym 100213F Counterfeit Money

    CodeForces Gym题目页面传送门 有\(1\)个\(n1\times m1\)的字符矩阵\(a\)和\(1\)个\(n2\times m2\)的字符矩阵\(b\),求\(a,b\)的最大公共 ...

  8. HDU 1880 魔咒词典(字符串哈希)

    题目链接 Problem Description 哈利波特在魔法学校的必修课之一就是学习魔咒.据说魔法世界有100000种不同的魔咒,哈利很难全部记住,但是为了对抗强敌,他必须在危急时刻能够调用任何一 ...

  9. 洛谷P3370 【模板】字符串哈希

    P3370 [模板]字符串哈希 143通过 483提交 题目提供者HansBug 标签 难度普及- 提交  讨论  题解 最新讨论 看不出来,这题哪里是哈希了- 题目描述 如题,给定N个字符串(第i个 ...

随机推荐

  1. POJ:3160-Father Christmas flymouse

    Father Christmas flymouse Time Limit: 1000MS Memory Limit: 131072K Description After retirement as c ...

  2. POJ:1086-Parencodings

    Parencodings Time Limit: 1000MS Memory Limit: 10000K Description Let S = s1 s2-s2n be a well-formed ...

  3. poj 3050 地图5位数问题 dfs算法

    题意:一个5*5地图上面,从任意位置上下左右跳五次,组成一个数.问:不重复的数有多少个? 思路:dfs 从任意位置跳5次,说明每个位置都需要遍历. 组成一个数:number*10+map[dx][dy ...

  4. 如何查看Android apk的包名?

    有以下四种方法可以查看apk的包名,之后有别的方法,会接着更新文档的. 1. 安装APK包名查看器; 2. 源码AndroidManifest.xml中查看package包名; 3. 利用" ...

  5. Python虚拟机函数机制之闭包和装饰器(七)

    函数中局部变量的访问 在完成了对函数参数的剖析后,我们再来看看,在Python中,函数的局部变量时如何实现的.前面提到过,函数参数也是一种局部变量.所以,其实局部变量的实现机制与函数参数的实现机制是完 ...

  6. Selenium WebDriver的多浏览器测试

    1. IE浏览器,需要配合下载IEDriverSever.exe的驱动程序,目前selenium支持IE9以上. (驱动程序下载链接:https://pan.baidu.com/s/1YpaUsIs1 ...

  7. day03_04 文件后缀及系统环境变量

    进入cmd,如果想直接切换盘符的话,操作如下 dir命令---查看目录下的文件及文件夹 cd命令---想进入某个目录,就是是双击文件夹进入目录的命令,按table键有神奇效果哦 cd ..命令---类 ...

  8. 思路清奇:通过 JavaScript 获取移动设备的型号

    我们一般在浏览器里识别用户的访问设备都是通过 User Agent 这个字段来获取的,但是通过它我们只能获取一个大概的信息,比如你用的是 Mac 还是 Windows,用的是 iPhone 还是 iP ...

  9. [git 学习篇] 提交文件

    http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013743256916071d ...

  10. [错误解决]UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)

    python2内容无法写入csv,报错:UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordin ...