字符串处理--HDU第1075解题报告

题目链接


该题目最初的想法是将没一行的字典数据用string接收,然后存入vector数组中。

然后题目的问题只变成了从vector的每个元素中查找火星人说的话,然后用英语替代。

可是写完后,时间顿时报表。原来是搜索占据了太大的时间。

下面是超时代码:

#include<iostream>
#include<string>
#include<vector>
#include<cstring>
using namespace std;

void translate(vector<string> &vec1,char *str);
int main()
{
   string str;
   int i = 0;
   int ch;
   char str1[11111];
   vector<string>vec1;
   getline(cin,str);//接收START
   getline(cin,str);//接收字典数据
   while(str != "END")//将END之前的字典数据存入容器中
   {
       vec1.push_back(str);
       getline(cin,str);
   }

   getline(cin,str);//接收start
   //采用别接收别翻译的方法来做,比较简单
   ch = cin.get();
   while(ch!='E')
   {
       i=0;
        while( ch>='a' && ch<='z')
       {
            str1[i] = ch;
            ch = cin.get();
            i++;
       }
       str1[i] = 0;//添加0结束标志
       if(i!=0)
       translate(vec1,str1);//翻译
       cout<<str1;//输出翻译之后的字符串
       cout<<(char)ch;//跳出循环的原因是因为接收到了标点符号,或者空格,或者回车
       ch = cin.get();
   }
   cin.get();
   cin.get();





}
void translate(vector<string>&vec1,char *str)
{
    int i;
    int j;
    bool mark = false;//用来标记死否找到
    int pos = 0;
    for(i=0;i!=vec1.size();++i)
    {
        pos = vec1[i].find(str);
        if( pos != string::npos)
        {
            mark = true;
            break;
        }
    }

    if(mark && vec1[i][pos-1]==' ' &&vec1[i].size() == pos+strlen(str))
    {
        for(j=0;j!=vec1[i].size() && vec1[i][j]!=' ';++j)
        {
            str[j] = vec1[i][j];//翻译
        }
        str[j] = 0;//添加结束标志
    }

}


看了题目后的讨论是说要用关联容器map或者字典树来做,可是这两者我都没有学过。

于是花了一个自修的时间学了map容器。

实现了下面的代码:

#include<iostream>
#include<sstream>
#include<string>
#include<map>
using namespace std;

void find(map<string,string>&dictionary,string str)
{
    map<string,string>::iterator iter;
    iter = dictionary.find(str);
    if(iter != dictionary.end())
        cout<<dictionary[str];
    else
        cout<<str;
}
int main()
{
   map<string,string> dictionary;//用来做字典
   map<string,string>::iterator iter ;
   string::iterator siter;
   string line;
   string word1,word2;
   char ch;
   int i;

   getline(cin,line);//接收START
   getline(cin,line);//接收字典数据
   while(line != "END")//没遇到END之前的数据都要加入字典
   {
	   istringstream stream(line);//从每行中读取单词
       stream>>word1;//读取值
       stream>>word2;//读取键
       dictionary[word2] = word1;//插入字典
       getline(cin,line);//接收新的数据
   }
   iter = dictionary.begin();


   getline(cin,line);//接收start
   getline(cin,line);
   while(line != "END")
   {
        for(i=0;i<line.size();++i)//接收行数据
        {

            ch = line[i];
            if(ch<='z' ||ch>='a')
            {   string str;
                while(i<line.size() && ch>='a' &&ch<='z')//提取每行的单词
                {
                    str.push_back(ch);
                    ++i;
                    ch = line[i];
                }
                find(dictionary,str);//替换单词,输出
                cout<<ch;//输出非单词字符
            }
            else
                cout<<ch;
        }
        cout<<endl;
        getline(cin,line);
   }
}





字典树 还没学,等有空学了再来重写代码。

提交了下别人用字典树写的代码,运行时间只有我用map容器的1/6

所以我一定要学会字典树。


这次AC,我学到了很多。yeah!!

好不容易学了字典树,重写代码,一提交,是比用map容器快多了,但是比别人用字典树写的代码慢多了。
一研究,原来是数据太大,而我又用C++的输入函数来录入数据,导致时间太慢,
所以以后录入大数据时,一定要用C语言的输入函数。

下面是字典树写的代码:
#include<iostream>
#include<string>
#include<sstream>

using namespace std;
const int MAX = 26;
struct node
{
    string word;//火星文对应的英文
    node *next[MAX];
    node()
    {
        for(int i=0;i!=MAX;++i)
        {
            next[i] = NULL;
        }
    }
};
class trie//字典树类
{
public:
    trie(){root = new node;}
    void creat_trie(string str,string word);
    void search(string str);
    void print_all();
private:
    node *root;
};

void trie ::creat_trie(string str,string word)//字典树的创建
{
    node *current = root;
    node *fresh;
    int index;
    for(int i=0;i<str.size();++i)
    {
        index = str[i] - 'a';
        if(current->next[index] == NULL)
        {
            fresh = new node;
            current->next[index] = fresh;
            current = current->next[index];
        }
        else
        {
            current = current->next[index];
        }

    }
    current->word = word;

}

void trie:: search(string str)
{
    node *current;
    current = root;
    int index;
    for(int i=0;i!=str.size();++i)//能够跳出循环说明了什么?说明该单词在字典树种或该单词是字典树中某个单词的前缀
    {
        index = str[i] - 'a';
        current = current->next[index];
        if(current == NULL)
        {
            cout<<str;
            return;
        }
    }
    //判断跳出循环的条件是为何
    if(current->word == "")//该单词是字典树中某个单词的前缀,即字典树中无该单词,不能翻译
        cout<<str;
    else//翻译
        cout<<current->word;

}


int main()
{

   string line;
   string word1,word2;
   char ch;
   int i;
   trie t;

   cin>>line;//接收START
   cin>>word1;
   cin>>word2;
   while(word1 != "END")//没遇到END之前的数据都要加入字典
   {


       t.creat_trie(word2,word1);
       cin>>word1;//读取值
       cin>>word2;//读取键

   }
   //第二个shart会被word2所读取

   cin.get();//接收回车
   getline(cin,line);//接收火星人的话
   while(line != "END")
   {
        for(i=0;i<line.size();++i)//接收行数据
        {

            ch = line[i];
            if(ch<='z' ||ch>='a')
            {   string str;
                while(i<line.size() && ch>='a' &&ch<='z')//提取每行的单词
                {
                    str.push_back(ch);
                    ++i;
                    ch = line[i];
                }
                t.search(str);
                cout<<ch;//输出非单词字符
            }
            else
                cout<<ch;
        }
        cout<<endl;
        getline(cin,line);
   }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值