123 - Searching Quickly

题意:
读入一组 ignore word 和一组line, 把在 line 中但不在 ignore word 中的单词做为 keywords; 把 keywords 按字典序从小到大进行输出包含其的句子(句子全转为小写,keyword 转为大写); 若一个 keyword 在一个句子中出现多次, 则按其出现位置, 从前到后进行输出.
注意: 
1. 如果一个 keyword 在多个句子中出现, 则按句子的读入顺序进行输出(不是按句子的字典序进行输出, 否则WA).
2. 一个 keyword 在一个句子中 必须是单词匹配, 而不能是单词中的某一部分匹配.

思路:
1. 把所在 line 中的单词都提取出来, 放到 set 里, set 会自动把重复的 keyword 去掉.
2. 把ignore word 中包含的单词去掉, 得到 keywords.
3. keywords 排序.
4. 按 keywords 从小到大, 查找包含 keyword 的各个句子, 进行输出.

要点:
1. vector 的 erase 操作时, 若其参数是一个 iterator, 必须先判断 iterator 是否为 end(), 否则会出现各种奇怪的问题.
2. string 的 replace 是直接影响原字符串, 而不是返回一个 replace 过的字符串.

题目:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=98&page=show_problem&problem=59

代码:

# include <iostream>
# include <string>
# include <cstdio>
# include <cstring>
# include <vector>
# include <algorithm>
# include <cctype>
# include <iterator>
# include <assert.h>
# include <set>
# include <sstream>   // stringstream
using namespace std;

// 输入的一行中有可能包含多个连续空格,所以不能直接以空格来分隔单词,否则会 WA

// 获取 keywords, 即不在 ignoreKeywords 里的都算
// 先把 titles 的所有 word 提取出来, 再减去 ignoreKeywords 中的即可
vector<string> getKeywords(const vector< vector<string> >& titles, 
                           vector<string> ignoreKeywords) {
  set<string> allWords;
  set<string>::iterator it;

  for (int i=0; i<titles.size(); i++) {
    vector<string> title = titles[i];

    for (int j=0; j<title.size(); j++)
      allWords.insert(title[j]);
  }

  for (int i=0; i<ignoreKeywords.size(); i++) {
    it = allWords.find(ignoreKeywords[i]);

    // 这里要加上这一个判断, 不然当 allWords 为 null 时,erase 就会出问题
    if (it != allWords.end())
      allWords.erase(it);
  }

  return vector<string>(allWords.begin(), allWords.end());
}


vector<string> splitBySpace(const string& line) {
  vector<string> vt;
  string word;

  size_t i = 0;
  size_t j = 0;

  while (i<line.size() && j<line.size()) {
    while (i < line.size()) {
      if (isalpha(line[i])) 
        break;
      ++i;
    }

    j = i+1;
    while (j < line.size()) {
      if (!isalpha(line[j])) {
        word = line.substr(i, j-i);
        vt.push_back(word);
        break;
      }

      ++j;

      // 最后一个单词
      if (j == line.size()) {
        word = line.substr(i, j-i);
        vt.push_back(word);
        break;
      }
    }

    i = j+1;
  }

  return vt;
}


int main(int argc, char const *argv[])
{
  #ifndef ONLINE_JUDGE
    freopen("123_i.txt", "r", stdin);  
    freopen("123_o.txt", "w", stdout); 
  #endif
  
  string line;

  // 输入
  vector<string> ignoreKeywords;
  while (!cin.eof()) {
    getline(cin, line);
    if (line == "::") break;

    transform(line.begin(), line.end(), line.begin(), ::tolower);
    ignoreKeywords.push_back(line);
  }


  vector< vector<string> > titles;
  vector<string> titleLines;
  while (!cin.eof()) {
    getline(cin, line);
    transform(line.begin(), line.end(), line.begin(), ::tolower);

    vector<string> words;
    words = splitBySpace(line);
    titles.push_back(words);
    titleLines.push_back(line);
  }

  // 得到 keywords
  vector<string> keywords = getKeywords(titles, ignoreKeywords);
  sort(keywords.begin(), keywords.end(), less<string>());

  vector<string>::iterator it;

  for (int i=0; i<keywords.size(); i++) {
    string keyword = keywords[i];
    size_t keywordSize = keyword.size();

    if (keywordSize == 0)
      continue;

    assert(keywordSize != 0);

    string upperKeyword = keyword;
    transform(keyword.begin(), keyword.end(), 
              upperKeyword.begin(), ::toupper);

    for (int i=0; i<titleLines.size(); i++) {
      string title = titleLines[i];

      if (title == keyword) {
        cout << upperKeyword << endl;
        continue;
      }

      size_t pos = title.find(keyword, 0);

      // 一行中包含多个 keyword,则按前到后进行输出
      while (pos != string::npos) {
        bool isSingleWord = false;

        // 必须是一个完整的单词,即不能是一个单词中的一部分
        if (pos == 0) {
          if (!isalpha(title[pos+keywordSize]))
            isSingleWord = true;
        } else if (pos+keywordSize == title.size()) {
          if (!isalpha(title[pos-1]))
            isSingleWord = true;
        } else {
          if (!isalpha(title[pos-1]) && !isalpha(title[pos+keywordSize]))
            isSingleWord = true;
        }

        if (isSingleWord) {
          string temp = title;
          cout << temp.replace(pos, keywordSize, upperKeyword) << endl;
        }

        pos = title.find(keyword, pos+keywordSize);
      }
    }
  }

  return 0;
}

环境: C++ 4.5.3 - GNU C++ Compiler with options: -lm -lcrypt -O2 -pipe -DONLINE_JUDGE



你可能感兴趣的:(123,uva,searching,Quickly)