第四题(共四题 100 分):低频词过滤( 40 分)
题目描述:请编写程序,从包含大量单词的文本中删除出现次数最少的单词。如果有多
个单词都出现最少的次数,则将这些单词都删除。
输入数据:程序读入已被命名为 corpus.txt 的一个大数据量的文本文件,该文件包含英
文单词和中文单词,词与词之间以一个或多个 whitespace 分隔。(为便于调试,您可下载
测试 corpus.txt 文件,实际运行时我们会使用不同内容的输入文件。)
输出数据:在标准输出上打印删除了 corpus.txt 中出现次数最少的单词之后的文本(
词与词保持原来的顺序,仍以空格分隔)。
评分标准:程序输出结果必须正确,内存使用越少越好,程序的执行时间越快越好。
my answer:
吸取前面的教训,尽量考虑多种情况,能处理单个或多个空格,换行,单个或多个空行
最正常的算法,三遍循环:
第一遍,计算每个单词的频率。第二遍,求最小频率。第三遍,输出。
没想到什么时间或空间的优化
#include <iostream>
#include <fstream>
#include <string>
#include <map>
using namespace std;
map<string, int> M;
char c;
int main()
{
M.clear();
ifstream fin, fin2;
fin.open("corpus.txt");
string word;
while (fin>>word)
M[word]++;
int min = 0x7fffffff;
map<string,int>::iterator map_it = M.begin();
while(map_it != M.end())
{
if(map_it->second < min)
min = map_it->second;
++map_it;
}
fin.close();
// fin.seekg(0, ios_base::beg);
fin2.open("corpus.txt");
string str;
while(c = fin2.get())
{
if(c == '\0' || c == '\t' || c == '\n' || c == ' ')
{
if(str != "" && M[str] > min)
cout<<str;
str = "";
cout<<c;
}
else
str += c;
}
return 0;
}
牛A陈世熹的比赛答题源码:
也是三遍循环,差不多
#include <iostream>
#include <cstdio>
#include <cstring>
#include <utility>
#include <map>
using namespace std;
struct word_less
{
bool operator()(char* A, char* B) const
{
return strcmp(A, B) < 0;
}
};
typedef map<char*, int, word_less> my_map;
my_map Map;
int N, Min;
char Word[100001];
char* get_word()
{
char* P;
int Len;
Len = (int)strlen(Word);
P = new char[Len + 1];
strcpy(P, Word);
return P;
}
int main()
{
my_map::iterator It;
freopen("corpus.txt", "r", stdin);
Map.clear();
while (scanf("%s", Word) > 0)
{
It = Map.find(Word);
if (It == Map.end())
Map.insert(make_pair(get_word(), 1));
else
It->second++;
}
Min = 0x7fffffff;
for (It = Map.begin(); It != Map.end(); ++It) if (It->second < Min)
Min = It->second;
N = 0;
freopen("corpus.txt", "r", stdin);
while (scanf("%s", Word) > 0)
if (Map[Word] > Min)
{
if (N > 0) printf(" ");
N++;
printf("%s", Word);
}
printf("\n");
return 0;
}
牛B楼天城的比赛答题源码:
牛B的代码还是一如既往的难以理解,大概是用自己写的hash代替STL中的map
#include <stdio.h>
#include <string.h>
#include <unistd.h>
const int bufsize=128*1024;
int bufL;
char buf[bufsize];
struct THashPoint
{
char *s;
int c;
THashPoint *next;
};
int MemoryID=0;
THashPoint **Hash,*Memory;
char *text;
int L,HashSize,minC;
void ReadFile()
{
text=new char[bufsize+5];
L=0;
int textL=bufsize+5;
while (1)
{
bufL=read(0,buf,bufsize);
if (bufL==0)
break;
while (L+bufL>=textL)
{
char *t_text=text;
textL*=2;
text=new char[textL];
memcpy(text,t_text,L);
}
memcpy(text+L,buf,bufL);
L+=bufL;
}
text[L]=0;
}
bool Prime(int n)
{
for (int i=2;i*i<=n;i++)
if (n%i==0)
return false;
return true;
}
void Prepare()
{
int N=0,i;
for (i=0;i<L;i++)
if (text[i]==' ' || text[i]=='\t' || text[i]=='\n')
text[i]=0;
for (i=0;i<L;i++)
if ((i==0 || text[i-1]==0) && text[i]!=0)
N++;
for (HashSize=N*2+10;!Prime(HashSize);HashSize++);
Hash=new THashPoint* [HashSize];
for (i=0;i<HashSize;i++)
Hash[i]=NULL;
MemoryID=0;
Memory=new THashPoint[N+10];
}
int HashTable_function(char *s)
{
int address=strlen(s)%HashSize;
for (int i=0;s[i];i++)
address=(address*137+s[i]+128)%HashSize;
return address;
}
void HashTable_Insert(char *s)
{
int address=HashTable_function(s);
THashPoint *p;
for (p=Hash[address];p!=NULL;p=p->next)
if (strcmp(p->s,s)==0)
{
p->c++;
return;
}
p=&Memory[MemoryID++];
p->s=s;
p->c=1;
p->next=Hash[address];
Hash[address]=p;
}
bool Print(char *s)
{
int address=HashTable_function(s);
THashPoint *p;
for (p=Hash[address];p!=NULL;p=p->next)
if (strcmp(p->s,s)==0 && p->c==minC)
return false;
return true;
}
void Solve()
{
int i;
for (i=0;i<L;i++)
if ((i==0 || text[i-1]==0) && text[i]!=0)
HashTable_Insert(text+i);
minC=2000000000;
for (i=0;i<MemoryID;i++)
if (Memory[i].c<minC)
minC=Memory[i].c;
bool first=true;
for (i=0;i<L;i++)
if ((i==0 || text[i-1]==0) && text[i]!=0 && Print(text+i))
{
if (!first)
printf(" ");
first=false;
printf("%s",text+i);
}
}
int main()
{
freopen("corpus.txt","r",stdin);
ReadFile();
Prepare();
Solve();
return 0;
}