比较神奇的trie树。
当然不用对地图建8个trie,直接对单词建树即可。
枚举地图上的每个点和每个方向,深搜,在地图上边走、trie上边跑,如果找到单词结尾,那么就保存答案。
由于trie根节点并没有保存单词,所以深搜开始的节点是trie的儿子。
题目并没有告诉单词长度,一开始开了和地图一样的大小,结果MLE,最后开小了一个数量级,AC。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn = 1005, maxd = 26, maxnode = 100000; int n, m, k, sx, sy, delta[][2] = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}}; string g[maxn]; struct _data { int x, y, d; } ans[maxn]; struct _trie { int son[maxnode][maxd], triecnt, id[maxnode]; void init() { memset(son, 0, sizeof(son)); triecnt = 1; memset(id, 0, sizeof(id)); } void insert(string s, int w) { int now = 1, len = s.size(); for(int i = 0; i < len; i++) { int ind = s[i] - 'A'; if(!son[now][ind]) son[now][ind] = ++triecnt; now = son[now][ind]; } id[now] = w; } void dfs(int now, int x, int y, int d) { if(!now) return; if(id[now]) { ans[id[now]] = (_data) {sx, sy, d}; id[now] = 0; } x += delta[d][0]; y += delta[d][1]; if(x < 0 || x >= n || y < 0 || y >= m) return; dfs(son[now][g[x][y] - 'A'], x, y, d); } } trie; int main() { ios::sync_with_stdio(false); cin >> n >> m >> k; for(int i = 0; i < n; i++) cin >> g[i]; trie.init(); for(int i = 1; i <= k; i++) { string str; cin >> str; trie.insert(str, i); } for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) for(int d = 0; d < 8; d++) trie.dfs(trie.son[1][g[i][j] - 'A'], sx = i, sy = j, d); for(int i = 1; i <= k; i++) printf("%d %d %c\n", ans[i].x, ans[i].y, ans[i].d + 'A'); return 0; }