POJ 1204 Word Puzzles

解题思路:建立输入单词(反向,便于寻找起始点所在的位置)的AC图,然后按照八个方向依次寻找(注意方向也为方向)。例如A是向上方向,我们需要改为反向,向下。那么我们需要将每列--从上到下方向--组成的字符串--共width个--分别到AC图中查找匹配。

关键代码已经注释

 

#include <iostream>
using namespace std;



#define MAX_SIZE 1005
#define MAX_LEN 1005
#define MAX_NOD 1000001
#define initArray(array) memset(array, 0, sizeof(array))

/************************************************************************/
/* Descrption: 采用左孩子,右兄弟的结构实现AC自动机,母串前进的过程仍需采用
回溯的方法找到下一个匹配点, trie图是不需要回溯的
/* first - 当前节点的第一个孩子节点
/* next - 当前节点的兄弟节点
/* suffix - 后缀节点
/* queue - BFS 过程存储节点
/* id - 该危险节点所对应的单词,0表示其为安全节点
/* place - 单词所对应的危险节点编号
/* node - trie图节点的存储
/* letter - 当前字典树插入的单词
/* 其他(略)
/***********************************************************************
*/
int size, width, height;
int first[MAX_NOD], next[MAX_NOD], suffix[MAX_NOD], queue[MAX_NOD], id[MAX_NOD], place[MAX_LEN];
int wx[MAX_SIZE], wy[MAX_SIZE], wd[MAX_SIZE];
char node[MAX_NOD], letter[MAX_LEN];
char map[MAX_SIZE][MAX_SIZE];

// 8个方向,方向均为反方向,便于找到初始点位置
const int dir[8][2] = {{0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}};

void Build_Trie(int n)// 字典树中插入第n个单词
{
int p = 0, t;

for (int i = strlen(letter) - 1; i >= 0; i--) //从后往前插入,便于找到初始点
{
t
= first[p];
while (t && node[t] != letter[i]) t = next[t];
if (!t)
{
node[
++size] = letter[i];
next[size]
= first[p];
first[p]
= size;
first[size]
= 0;
p
= size;
}
else
p
= t;
}
id[p]
= n, place[n] = p;
}

int Child(int x, char c)// 求取x的c孩子
{
int t;
while (true)
{
t
= first[x];
while(t && node[t] != c)t = next[t];
if(t || !x) break;
x
= suffix[x];// 如果当前节点不存在c孩子,则到后缀结点中寻找
}
return t;
}

void Build_Graph()// 建立AC图
{
int head = 0, tail = 0;
queue[
0] = 0;
while (head <= tail)
{
if (first[queue[head]])
{
queue[
++tail] = first[queue[head]];
while(true)
{
if (head == 0) suffix[queue[tail]] = 0;
else
{
suffix[queue[tail]]
= Child(suffix[queue[head]], node[queue[tail]]);
if (id[queue[tail]] == 0 && id[suffix[queue[tail]]])//如果后缀结点是危险节点,则该节点也是危险节点
id[queue[tail]] = id[suffix[queue[tail]]];
}
if (!next[queue[tail]])break;
queue[
++tail] = next[queue[tail - 1]];
}
}
head
++;
}
}

void scan(int x, int y, int dirIndex)
{
int t, p = 0;
while (x >= 0 && x < width && y >=0 && y < height)
{
p
= Child(p, map[y][x]); t = id[p];
while(t > 0)
{
wx[t]
= x, wy[t] = y, wd[t] = dirIndex;// 防止字串包含的情况,如(abc与bc)
t = id[suffix[place[t]]];
}
x
+= dir[dirIndex][0];
y
+= dir[dirIndex][1];
}
}
int main()
{
int dirIndex, i, w;
bool flag;
size
= 0;
scanf(
"%d %d %d", &height, &width, &w);
for (i = 0; i < height; i++)
scanf(
"%s", map[i]);
initArray(first), initArray(next), initArray(id);
for(i = 0; i < w; i++)
{
scanf(
"%s", letter);
Build_Trie(i
+1);
}
Build_Graph();
memset(wd,
-1, sizeof(wd));
dirIndex
= 0; for (i = 0; i < width; i++)scan(i, 0, dirIndex);
for (i = 0, flag = true; (i <= w) && flag; i++) if(wd[i] == -1)flag = false;
if (!flag)
{
dirIndex
= 1; for (i = 1; i < width; i++)scan(i, 0, dirIndex);
for (i = 1; i < (height - 1); i++) scan(width - 1, i, dirIndex);
for (i = 1, flag = true; (i <= w) && flag; i++) if(wd[i] == -1)flag = false;
}
if(!flag)
{
dirIndex
= 2; for (i = 0; i < height; i++)scan(width - 1, i, dirIndex);
for (i = 1, flag = true; (i <= w) && flag; i++) if(wd[i] == -1)flag = false;
}
if (!flag)
{
dirIndex
= 3; for (i = 1; i < width; i++)scan(i, height - 1, dirIndex);
for (i = 1; i < height - 1; i++)scan(width - 1, i, dirIndex);
for (i = 1, flag = true; (i <= w) && flag; i++) if(wd[i] == -1)flag = false;
}
if (!flag)
{
dirIndex
= 4; for (i = 0; i< width; i++) scan(i, height - 1, dirIndex);
for (i = 1, flag = true; (i <= w) && flag; i++) if(wd[i] == -1)flag = false;
}
if (!flag)
{
dirIndex
= 5; for (i = 1; i < height; i++)scan(0, i, dirIndex);
for (i = 1; i < width - 1; i++)scan(i, height - 1, dirIndex);
for (i = 1, flag = true; (i <= w) && flag; i++) if(wd[i] == -1)flag = false;
}
if (!flag)
{
dirIndex
= 6; for (i = 0; i < height; i++)scan(0, i, dirIndex);
for (i = 1, flag = true; (i <= w) && flag; i++) if(wd[i] == -1)flag = false;
}
if (!flag)
{
dirIndex
= 7; for (i = 0; i < height - 1; i++)scan(0, i, dirIndex);
for (i = 1; i < width - 1; i++)scan(i, 0, dirIndex);
}
for (i = 1; i <= w; i++)
printf(
"%d %d %c\n", wy[i], wx[i], char(wd[i]+'A'));

return 0;
}

 

 

posted on 2010-11-24 20:19  ltang  阅读(888)  评论(0编辑  收藏  举报

导航