Re[2]: Помогите реализовать алгоритм
От: investigator Россия  
Дата: 23.09.04 12:23
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Здравствуйте, momart, Вы писали:


M>>Здравствуйте!

M>>Есть такая задача:
M>>строка [word1] bla-bla-bla [word2] tra-ta-ta [word1] be-be-be [word3] a-a-a [word2] и так далее. Надо оставить только первые вхождения слов в скобках:
M>>[word1] bla-bla-bla [word2] tra-ta-ta be-be-be [word3] a-a-a

K>вот мой вариант:

K>
K>#include <iostream>
K>#include <string>
K>#include <vector>

K>template<typename Iterator>
K>class tokenizer
K>{
K>private: 
K>    tokenizer(const tokenizer&);
K>    tokenizer& operator=(const tokenizer&);
K>public:
K>    struct token
K>    {
K>        Iterator first;
K>        Iterator last;
K>    };    

K>public:
K>    tokenizer()
K>    {
K>    }
    
K>    void set_str(Iterator first, Iterator last)
K>    {    
K>        first_    = first;
K>        last_    = last;
K>        current_= first_;
K>    }
    
K>    token current_token()
K>    {
K>        return token_;
K>    }
    
K>    bool next();

K>private:
K>    Iterator    first_;
K>    Iterator    last_;
K>    Iterator    current_;

K>    token        token_;
K>};

K>//-----------------------------------------------------------------------
K>template<typename Iterator>
K>bool tokenizer<Iterator>::next()
K>{
K>    if (current_ == last_) 
K>    {
K>        return false;
K>    }

K>    while (current_ != last_ && *current_ != '[') 
K>    {
K>        ++current_;
K>    }

K>    if (current_ == last_) 
K>    {
K>        return false;
K>    }

K>    unsigned count = 0;
K>    Iterator p = current_;

K>    while (p != last_ && *p != ']') 
K>    {
K>        ++p;
K>        ++count;
K>    }

K>    ++count;

K>    if (p == last_) 
K>    {
K>        return false;
K>    }

K>    token_.first = current_;
K>    token_.last  = current_ + count;

K>    current_ += count;

K>    return true;
K>}

K>//-----------------------------------------------------------------------
K>int main()
K>{
K>    std::string str("[word1] bla-bla-bla [word2] tra-ta-ta [word1] be-be-be [word3] a-a-a [word2]");

K>    typedef tokenizer<std::string::iterator> tokenizer;
    
K>    tokenizer tok;
K>    tok.set_str(str.begin(), str.end());

K>    std::vector<tokenizer::token> tokens;

K>    while (tok.next())
K>    {
K>        tokenizer::token tk = tok.current_token();

K>        std::vector<tokenizer::token>::iterator it   = tokens.begin();
K>        std::vector<tokenizer::token>::iterator last = tokens.end();

K>        for (;it != last; ++it)
K>        {
K>            if (std::distance(it->last, it->first) == std::distance(tk.last, tk.first) && 
K>                std::string(it->first, it->last) == std::string(tk.first, tk.last))
K>            {
K>                tok.set_str(str.erase(tk.first, tk.last), str.end());
K>            }
K>        }

K>        tokens.push_back(tok.current_token());
K>    }

K>    std::cout << str << std::endl;
K>}
K>


K>кто будет критиковать код сразу сообщаю, что я писал его уставший и ,честно говоря, немного выпивший, так что особо не ругайте.


И все-таки покритикуем. Правда не код, а алгоритм. Здесь все хорошо за исключением квадратичности. Лучше вместо внутреннего цикла использовать HashSet для проверки того, что такой тоукен уже встречался. Алгоритм будет работать в N раз быстрее (где N-количество слов в []).

Можно подумать и о том, чтобы заменить удаление во внутреннем цикле на добавление к результирующей строке. В крайнем случае сейчас мы произведем N-1 удаление, при этом всего произойдет N-1 копирование ВСЕЙ оставшейса строки.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.