第三题(共四题 100 分):字符串替换( 30 分)
题目描述:请编写程序,根据指定的对应关系,把一个文本中的字符串替换成另外的字符串。
输入数据:程序读入已被命名为 text.txt 和 dict.txt 的两个输入数据文本文件, text.txt 为一个包含大量字符串(含中文)的文本,以 whitespace 为分隔符; dict.txt 为表示字符串( s1 )与字符串( s2 )的对应关系的另一个文本(含中文),大约在 1 万行左右,每行两个字符串(即 s1 和 s2 ),用一个 \t 或空格分隔。 dict.txt 中各行的 s1 没有排序,并有可能有重复,这时以最后出现的那次 s1 所对应的 s2 为准。 text.txt 和 dict.txt 中的每个字符串都可能包含除 whitespace 之外的任何字符。 text.txt 中的字符串必须和 dict.txt 中的某 s1 完全匹配才能被替换。(为便于调试,您可下载测试 text.txt 和 dict.txt 文件,实际运行时我们会使用不同内容的输入文件。)
输出数据:在标准输出上打印 text.txt 被 dict.txt 替换后了的整个文本。
评分标准:程序输出结果必须正确,内存使用越少越好,程序的执行时间越快越好。
my answer:
这题又想多了,什么字典树的,后来用了map映射就好了。
如果单词之间有多个空格的情况没有考虑
没想到什么空间或者时间上的优化
必须要用fin1和fin2分别打开两个文件,不知道为什么
#include <iostream>
#include <fstream>
#include <map>
#include <string>
using namespace std;
map<string, string> M;
int main()
{
M.clear();
ifstream fin1, fin2;
fin1.open("dict.txt");
string a, b, word;
while (fin1>>a>>b)
{
M[a] = b;
}
fin1.close();
bool flag = 0;
fin2.open("text.txt");
while(fin2>>word)
{
if(flag)cout<<' ';
if(M[word]!="\0")
cout<<M[word];
else
cout<<word;
flag = 1;
}
fin2.close();
return 0;
}
牛A陈世熹的比赛答题源码:
思路似乎和我差不多,不明白为什么要写得这么复杂,也许是优化
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct word_less
{
bool operator()(const pair<char*, char*>& A, const pair<char*,
char*>& B) const
{
return strcmp(A.first, B.first) < 0;
}
};
int N, M;
pair<char*, char*> List[100000];
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()
{
freopen("dict.txt", "r", stdin);
N = 0;
while (scanf("%s", Word) > 0)
{
List[N].first = get_word();
scanf("%s", Word);
List[N].second = get_word();
N++;
}
stable_sort(List, List + N, word_less());
freopen("text.txt", "r", stdin);
M = 0;
while (scanf("%s", Word) > 0)
{
if (M > 0) printf(" ");
M++;
pair<char*, char*>* It = upper_bound(List, List + N,
make_pair((char*)Word,(char*) 0), word_less());
if (It > List && strcmp(It[-1].first, Word) == 0)
printf("%s", It[-1].second);
else
printf("%s", Word);
}
printf("\n");
return 0;
}
牛B楼天城的比赛答题源码:
终于有一题目是看懂了的,用的是自己写的hash,大概这样比较省空间,考虑到了单词之间有多个空格、TAB、换行的情况
#include <stdio.h>
#include <string.h>
#include <unistd.h>
//buf
const int bufsize=128*1024;
int bufL,bufP;
char buf[bufsize];
char readchar()
{
if (bufL==bufP)
{
bufL=read(0,buf,bufsize);
if (bufL==0)
return 0;
bufP=0;
}
return buf[bufP++];
}
//data
const int max_strlen=512*1024;
const int hashsize=30011;
struct THashPoint
{
char *s1,*s2;
THashPoint *next;
};
char lines[max_strlen],*s1,*s2;
FILE *f;
THashPoint *Hash[hashsize];
bool read_str()
{
lines[0]=0;
fgets(lines,max_strlen,f);
if (strlen(lines)>0 && lines[strlen(lines)-1]=='\n')
lines[strlen(lines)-1]=0;
if (strlen(lines)<3)
return false;
for (int i=0;lines[i];i++)
if (lines[i]==' ' || lines[i]=='\t')
{
s1=lines;
s2=lines+i+1;
lines[i]=0;
return true;
}
return false;
}
int HashTable_function(char *s)
{
int address=strlen(s)%hashsize;
for (int i=0;s[i];i++)
address=(address*107+s[i]+128)%hashsize;
return address;
}
void HashTable_Insert()
{
int address=HashTable_function(s1);
THashPoint *p;
for (p=Hash[address];p!=NULL;p=p->next)
if (strcmp(p->s1,s1)==0)
{
p->s2=new char[strlen(s2)+1];
strcpy(p->s2,s2);
return;
}
p=new THashPoint;
p->s1=new char[strlen(s1)+1];
p->s2=new char[strlen(s2)+1];
strcpy(p->s1,s1);
strcpy(p->s2,s2);
p->next=Hash[address];
Hash[address]=p;
}
void Print(char *s)
{
int address=HashTable_function(s);
THashPoint *p;
for (p=Hash[address];p!=NULL;p=p->next)
if (strcmp(p->s1,s1)==0)
{
printf("%s",p->s2);
return;
}
printf("%s",s);
}
void Init_HashTable()
{
f=fopen("dict.txt","r");
while (read_str())
HashTable_Insert();
fclose(f);
}
int main()
{
Init_HashTable();
//Main
freopen("text.txt","r",stdin);
bufL=bufP=0;
int L=0;
for (char c;(c=readchar())!=0;)
if (c==' ' || c=='\t' || c=='\n')
{
lines[L]=0;
Print(lines);
printf("%c",c);
L=0;
}
else
lines[L++]=c;
lines[L]=0;
Print(lines);
return 0;
}