poj 1204 Word Puzzles
·
题目来源:http://poj.org/problem?id=1204
题意:给你一个矩阵,矩阵里面存放着一些字符,问给出的字符串,是否在矩阵中,并判断在该字符串的首个字符在矩阵中的位置,以及该字符串的方向(可以看一下样例,就明白了).
正北标记为'A',东北标记为'B',类似以顺时针并按字典序标记方向,即到'H'表示西北方向。
ac自动机来做的,事实上,这个题还可以利用深搜来求解。
ac自动机比较好的参考资料:http://download.csdn.net/detail/hearthougan/7316089
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1010;
struct Trie_Node
{
int index;
Trie_Node* pNext[26];
Trie_Node* pFail;
Trie_Node()
{
index = 0;
memset(pNext, NULL, sizeof(pNext));
pFail = NULL;
}
};
Trie_Node* pRoot;
Trie_Node* Q[MAXN*100];
char Graph[MAXN][MAXN];
int row, col;
int dir[8][2] = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}};//这一块需要注意,数组的方向跟实际坐标的方向是不一样的
int Len[MAXN], res[MAXN][3];
bool IsCanGo(int x, int y)
{
if(x < 0 || x >= row || y < 0 || y >= col)
return false;
return true;
}
void Build_Trie(char* str, int id)//建立字典树
{
int j, i = 0;
Trie_Node* p = pRoot;
while(str[i])
{
j = str[i++] - 'A';
if(p->pNext[j] == NULL)
p->pNext[j] = new Trie_Node;
p = p->pNext[j];
}
p->index = id;
}
void Build_Fail()//建立失败指针
{
Trie_Node* tmp;
Trie_Node* p;
int qs = 0, qe = 0, i;
Q[qe++] = pRoot;
pRoot->pFail = NULL;
while(qs < qe)
{
tmp = Q[qs++];
p = NULL;
for(i = 0; i < 26; ++i)
{
if(tmp->pNext[i] != NULL)
{
if(tmp == pRoot)
tmp->pNext[i]->pFail = pRoot;
else
{
p = tmp->pFail;
while(p != NULL)
{
if(p->pNext[i] != NULL)
{
tmp->pNext[i]->pFail = p->pNext[i];
break;
}
p = p->pFail;
}
if(p == NULL)
tmp->pNext[i]->pFail = pRoot;
}
Q[qe++] = tmp->pNext[i];
}
}
}
}
void Query_Trie(int x, int y, int d)//查询
{
int j;
Trie_Node* p = pRoot;
Trie_Node* tmp;
while(IsCanGo(x, y))//多模同时匹配
{
j = Graph[x][y] - 'A';
while(p->pNext[j] == NULL && p != pRoot)//如果p是指向叶子节点,那么就找他的失败指针指向的结点
p = p->pFail;
p = p->pNext[j] == NULL ? pRoot : p->pNext[j];
tmp = p;//所谓多模同时匹配,关键点就是在这里,每到达一个节点,就查看它的失败指针指向的节点,是否也是一个单词的结尾
while(tmp != pRoot && tmp->index > 0)
{
res[tmp->index][0] = x - Len[tmp->index]*dir[d][0];//模式串所在位置的横、纵坐标
res[tmp->index][1] = y - Len[tmp->index]*dir[d][1];
res[tmp->index][2] = d;//搜寻的方向
tmp->index = 0;
tmp = tmp->pFail;
}
x = x + dir[d][0];
y = y + dir[d][1];
}
}
void Delete_Trie(Trie_Node* p)
{
int i;
Trie_Node* tmp = p;
for(i = 0; i < 26; ++i)
if(tmp->pNext[i])
Delete_Trie(tmp->pNext[i]);
delete tmp;
}
int main()
{
int subnum, i, j;
char str[MAXN];
while(~scanf("%d %d %d", &row, &col, &subnum))
{
pRoot = new Trie_Node;
memset(res, 0, sizeof(res));
for(i = 0; i < row; ++i)
scanf("%s", Graph[i]);
for(i = 1; i <= subnum; ++i)
{
scanf("%s", str);
Len[i] = strlen(str)-1;
Build_Trie(str, i);
}
Build_Fail();
for(i = 0; i < row; ++i)//按每一行的字符串进行匹配
{
for(j = 0; j < 8; ++j)
{
Query_Trie(i, 0, j);//正着扫一下
Query_Trie(i, col-1, j);//反着扫一下
}
}
for(i = 0; i < col; ++i)
{
for(j = 0; j < 8; ++j)
{
Query_Trie(0, i, j);
Query_Trie(row-1, i, j);
}
}
for(i = 1; i <= subnum; ++i)
printf("%d %d %c\n", res[i][0], res[i][1], res[i][2]+'A');
Delete_Trie(pRoot);
}
return 0;
}
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)