题意:
在一个给定的字符串矩阵中查找一个单词(当第一个字符匹配后,可以往八个方向查找后面的字符), 返回单词第一次出现的行数及第一个字母所在的列数.
思路:
1. 由于比较时不区分大小写, 所以每行字符串读进来后都选统一转成大写.
2. 查找时, 因为如果一个单词出现超过一次, 也是取其最左上的结果, 所以遍历时, 从左往右, 从上往下进行遍历;
3. 当第一个字母匹配后, 后面的字母可以向八个方向进行查找, 若全能找到, 则说明找到此单词.
4. 注意是整个单词统一向某一个方向进行查找, 即统一从左向右, 或统一从下往上, 不能说每一个字母都是对其所在位置往八个方向进行查找, 我就是理解错了这一点, 导致 WA 了好多次;
要点:
1. 使用数组 {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {1, -1}, {-1, 1}, {1, 1}}; 可以把{左,右,上,下,左上,左下,右上,右下} 方向的遍历都有效抽像出来, 而不需要单独写八段函数.
2. 使用 transform(line.begin(), line.end(), line.begin(), ::toupper); 把 line 里的字符都转成大写, 这里要注意 ::toupper, 必须加上全局空间标识符, 因为它不属于 std 命名空间.
3. g++ 编译的程序, 如果函数标明了返回 string, 最后却没有返回, 就会报段错误. 记得以前VC下不会的, 难道我记错了?
题目:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=96&page=show_problem&problem=951
代码:
# include <iostream> # include <string> # include <cstdio> # include <vector> # include <algorithm> # include <string.h> using namespace std; const int DIRECTION_NUM = 8; const int directions[8][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {1, -1}, {-1, 1}, {1, 1}}; // {左,右,上,下,左上,左下,右上,右下} // transform 把字符串转成大写, 这里要写成 ::toupper, 不能直接 toupper, 因为这个不是在 std 命名空间里的 // 查找 word 在 grid 中的位置, 返回结果就是 "所在行 第一列 " 组合的字符串 string searchWord(const vector<string>& grid, const string& word) { const int r = grid.size(); const int c = grid[0].size(); int searchedNum = 0; for(int i=0; i<r; i++){ for(int j=0; j<c; j++){ // 如果第一个字符查到了,就向八个方向遍历后面所有的字符,看是否匹配 if(grid[i][j] == word[0]){ for(int d=0; d<DIRECTION_NUM; d++){ searchedNum = 1; for(int k=1; k<word.size(); k++){ int row = i + directions[d][0] * k; int col = j + directions[d][1] * k; if(!(row >= 0 && row < r && col >= 0 && col < c)){ break; } if(grid[row][col] == word[k]){ ++searchedNum; }else{ break; } } if(searchedNum == word.size()){ char a[22]; sprintf(a, "%d %d", i+1, j+1); return a; } } } } } // 这里不写 return "not found", 当serache为 false 时,走到这里,就会报段错误 ... return "not found"; } int main(int argc, char const *argv[]) { #ifndef ONLINE_JUDGE freopen ("10010_i.txt", "r", stdin); freopen ("10010_o.txt", "w", stdout); #endif int caseNum; cin >> caseNum; while(caseNum--){ int m; int n; cin >> m >> n; vector<string> grid; for(int i=0; i<m; i++){ string line; cin >> line; // 统一转成大写 transform(line.begin(), line.end(), line.begin(), ::toupper); grid.push_back(line); } int k; cin >> k; for(int i=0; i<k; i++){ string word; cin >> word; // 统一转成大写 transform(word.begin(), word.end(), word.begin(), ::toupper); cout << searchWord(grid, word) << endl; } // 除了最后一个,都需要输出空行 if(caseNum > 0) cout << endl; } return 0; }
环境:C++ 4.5.3 - GNU C++ Compiler with options: -lm -lcrypt -O2 -pipe -DONLINE_JUDGE