AC自动机 - Word Puzzles - POJ - 1204
题意:
给 定 一 个 l × c 的 字 符 矩 阵 , 以 及 w 个 字 符 串 , 需 要 找 出 w 个 字 符 串 在 矩 阵 中 出 现 的 位 置 。 输 出 字 符 串 第 一 个 字 符 的 坐 标 以 及 字 符 串 的 “ 方 向 ” ( 共 8 个 方 向 ) , 由 8 个 字 母 A − H 表 示 8 个 方 向 , 从 A 开 始 代 表 北 , 顺 时 针 依 次 为 B , C , D , . . . , H 。 给定一个l×c的字符矩阵,以及w个字符串,需要找出w个字符串在矩阵中出现的位置。\\输出字符串第一个字符的坐标以及字符串的“方向”(共8个方向),\\由8个字母A-H表示8个方向,从A开始代表北,顺时针依次为B,C,D,...,H。 给定一个l×c的字符矩阵,以及w个字符串,需要找出w个字符串在矩阵中出现的位置。输出字符串第一个字符的坐标以及字符串的“方向”(共8个方向),由8个字母A−H表示8个方向,从A开始代表北,顺时针依次为B,C,D,...,H。
Sample Input:
20 20 10
QWSPILAATIRAGRAMYKEI
AGTRCLQAXLPOIJLFVBUQ
TQTKAZXVMRWALEMAPKCW
LIEACNKAZXKPOTPIZCEO
FGKLSTCBTROPICALBLBC
JEWHJEEWSMLPOEKORORA
LUPQWRNJOAAGJKMUSJAE
KRQEIOLOAOQPRTVILCBZ
QOPUCAJSPPOUTMTSLPSF
LPOUYTRFGMMLKIUISXSW
WAHCPOIYTGAKLMNAHBVA
EIAKHPLBGSMCLOGNGJML
LDTIKENVCSWQAZUAOEAL
HOPLPGEJKMNUTIIORMNC
LOIUFTGSQACAXMOPBEIO
QOASDHOPEPNBUYUYOBXB
IONIAELOJHSWASMOUTRK
HPOIYTJPLNAQWDRIBITG
LPOINUYMRTEMPTMLMNBO
PAFCOPLHAVAIANALBPFS
MARGARITA
ALEMA
BARBECUE
TROPICAL
SUPREMA
LOUISIANA
CHEESEHAM
EUROPA
HAVAIANA
CAMPONESA
Sample Output:
0 15 G
2 11 C
7 18 A
4 8 C
16 13 B
4 15 E
10 3 D
5 1 E
19 7 C
11 11 H
数据范围:
l
,
c
,
w
∈
[
1
,
1000
]
。
T
i
m
e
l
i
m
i
t
:
5000
m
s
M
e
m
o
r
y
l
i
m
i
t
:
65536
k
B
l,c,w∈[1,1000]。\\Time \ limit:5000 ms\ Memory \ limit:65536 kB
l,c,w∈[1,1000]。Time limit:5000ms Memory limit:65536kB
题解:
对 k 个 字 符 串 建 T r i e 图 , 接 着 对 每 个 字 符 暴 力 搜 索 八 个 方 向 在 图 上 匹 配 , 记 下 匹 配 成 功 的 坐 标 和 方 向 即 可 。 对k个字符串建Trie图,接着对每个字符暴力搜索八个方向在图上匹配,记下匹配成功的坐标和方向即可。 对k个字符串建Trie图,接着对每个字符暴力搜索八个方向在图上匹配,记下匹配成功的坐标和方向即可。
具体落实:
① 、 建 T r i e 图 , 插 入 的 过 程 中 给 每 个 结 尾 字 符 打 标 记 , 每 个 单 词 的 i d 记 为 其 输 入 的 序 号 , 方 便 匹 配 成 功 的 判 断 。 ② 、 爆 搜 的 过 程 可 以 从 矩 阵 四 条 边 上 的 点 进 入 , 来 减 少 重 复 搜 索 , 同 时 也 能 避 免 遗 漏 , 保 证 每 种 可 能 性 均 被 搜 到 。 ①、建Trie图,插入的过程中给每个结尾字符打标记,每个单词的id记为其输入的序号,方便匹配成功的判断。\\②、爆搜的过程可以从矩阵四条边上的点进入,来减少重复搜索,同时也能避免遗漏,保证每种可能性均被搜到。 ①、建Trie图,插入的过程中给每个结尾字符打标记,每个单词的id记为其输入的序号,方便匹配成功的判断。②、爆搜的过程可以从矩阵四条边上的点进入,来减少重复搜索,同时也能避免遗漏,保证每种可能性均被搜到。
代码:
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
const int N=1010;
using namespace std;
int l, c, idx = 1, w,ans[N][3], len[N];
char s[N][N], s2[N],dir[N];
int dx[] = { -1, -1, 0, 1, 1, 1, 0, -1 };
int dy[] = { 0, 1, 1, 1, 0, -1, -1, -1 };
struct node
{
int tr[30], id, fail;
}e[N * 110];
void Insert(char *str,int x)
{
int u = 1;
for (int i = 0;str[i]; i++)
{
int t = str[i] - 'A';
if (!e[u].tr[t])
e[u].tr[t] = ++idx;
u = e[u].tr[t];
}
e[u].id = x;
}
void build()
{
for (int i = 0; i < 26; i++)
e[0].tr[i] = 1;
queue <int> q;
q.push(1);
while (!q.empty())
{
int u = q.front();
q.pop();
int fail = e[u].fail;
for (int i = 0; i < 26; i++)
{
int y = e[u].tr[i];
if (y)
{
e[y].fail = e[fail].tr[i];
q.push(y);
}
else
e[u].tr[i] = e[fail].tr[i];
}
}
}
void dfs(int sx, int sy, int d)
{
int x = sx, y = sy, u = 1;
while (x >= 1 && x <= l && y >= 1 && y <= c)
{
while (u && !e[u].tr[s[x][y] - 'A'])
u = e[u].fail;
u = e[u].tr[s[x][y] - 'A'];
if (e[u].id)
{
ans[e[u].id][1] = x - (len[e[u].id] - 1) * dx[d]; ///回到第一个字母
ans[e[u].id][2] = y - (len[e[u].id] - 1) * dy[d];
dir[e[u].id] = d;
}
x += dx[d];
y += dy[d];
}
}
int main()
{
scanf("%d%d%d", &l, &c, &w);
for (int i = 1; i <= l; i++)
scanf("%s", s[i] + 1);
for (int i = 1; i <= w; i++)
{
scanf("%s", s2);
len[i] = strlen(s2);
Insert(s2,i);
}
build();
for (int i = 1; i <= l; i++)
for (int j = 0; j < 8; j++)
dfs(i, 1, j), dfs(i, c, j);
for (int i = 1; i <= c; i++)
for (int j = 0; j < 8; j++)
dfs(1, i, j), dfs(l, i, j);
for (int i = 1; i <= w; i++)
printf("%d %d %c\n", ans[i][1] - 1, ans[i][2] - 1, dir[i] + 'A');
return 0;
}