标签:class return r++ size watch tin uil inline direct
AC自己主动机的灵活运用,本题关键是灵活二字。
由于数据不是非常大。时间要求也不高的缘故。所以本题有人使用暴力法也过了。有人使用Trie。然后枚举八个方向,也过了。只是速度非常慢。
当然有人使用AC自己主动机没AC的,在讨论区里喊AC自己主动机超时的,那是由于不会灵活运用。或者是硬套模板的,AC了速度也不会快。
给出本人的算法思路:
1 把须要查找的keyword建立Trie, 然后构造AC自己主动机
2 查找的时候分八个方向查找,比方棋盘是board[N][M]。那么就能够循环i(0->N-1)。然后每次把board[i]当做一个文本。做过HDU的key word那道题目的人都知道怎样搜索一个文本中有多少keyword出现,这样不就把本题转换为查找文本keyword的问题了。 只是本题是须要八个方向的八个文本都搜索一遍,八是个不大的常数。其它方向怎样构造一个文本。就能够自己思考一下,不难。
3 记录结果就看个人的编程能力了,这里的技巧是逆转keyword建立Trie。那么搜索到尾就是每一个keyword的开头了。
AC自己主动机尽管高级,可是也还是一个算法工具。套模板。一大抄的代码没什么意义的,还是彻底消化掉,然后灵活运用才是关键。
对于本题写出高效的算法,那么是超过5星级难度的。
以下给出个上面思路的实现算法,速度非常快的。
出处: http://blog.csdn.net/kenden23
#include <stdio.h>
#include <string.h>
#include <queue>
using std::queue;
const int MAX_LEN = 1001;
const int ARR_SIZE = 26;
char board[MAX_LEN][MAX_LEN];
char word[MAX_LEN], gDir[MAX_LEN];
int gIndices[MAX_LEN][2];
int L, C, W;
inline int getIndex(char ch) { return ch-‘A‘; }
struct Node
{
int n, index;
Node *fail;
Node *arr[ARR_SIZE];
};
void clearNode(Node *p)
{
p->n = 0;
p->index = 0;
p->fail = NULL;
for (int i = 0; i < ARR_SIZE; i++)
{
p->arr[i] = NULL;
}
}
Node gPool[MAX_LEN*MAX_LEN];
int gPoolId;
Node *Trie;
void insertTrie(char w[], int index)
{
Node *pCrawl = Trie;
int len = strlen(w);
for (int i = len-1; i >= 0; i--)//逆向插入字符串。方便找到起头节点
{
int id = getIndex(w[i]);
if (!pCrawl->arr[id])
{
pCrawl->arr[id] = &gPool[gPoolId++];
clearNode(pCrawl->arr[id]);
}
pCrawl = pCrawl->arr[id];
}
pCrawl->n++;
pCrawl->index = index;
}
void buildFail()
{
queue<Node *> qu;
qu.push(Trie);
while (!qu.empty())
{
Node *pCrawl = qu.front();
qu.pop();
for (int i = 0; i < ARR_SIZE; i++)
{
if (!pCrawl->arr[i]) continue;
pCrawl->arr[i]->fail = Trie;
Node *fail = pCrawl->fail;
while (fail)
{
if (fail->arr[i])
{
pCrawl->arr[i]->fail = fail->arr[i];
break;
}
fail = fail->fail;
}
qu.push(pCrawl->arr[i]);
}
}
}
void searchDirect(int r, int c, int rDir, int cDir, char dir)
{
Node *pCrawl = Trie;
while (0<=r && 0<=c && r < L && c < C)
{
int id = getIndex(board[r][c]);
while (!pCrawl->arr[id] && pCrawl != Trie) pCrawl = pCrawl->fail;
if (pCrawl->arr[id])
{
pCrawl = pCrawl->arr[id];
Node *tmp = pCrawl;
while (tmp && tmp->n != -1)
{
if (tmp->n)//record results
{
gIndices[tmp->index][0] = r;
gIndices[tmp->index][1] = c;
gDir[tmp->index] = dir;
}
tmp->n = -1;
tmp = tmp->fail;
}
}
r += rDir, c += cDir; //Watch out, if we use "continue"!
}
}
void searchAll()
{
char dir = ‘E‘, counterDir = ‘A‘;
for (int c = 0; c < C; c++)
{
searchDirect(L-1, c, -1, 0, dir);
searchDirect(0, c, 1, 0, counterDir);
}
dir = ‘G‘, counterDir = ‘C‘;
for (int r = 0; r < L; r++)
{
searchDirect(r, 0, 0, 1, dir);
searchDirect(r, C-1, 0, -1, counterDir);
}
dir = ‘H‘, counterDir = ‘D‘;
for (int c = 0; c < C; c++)
{
searchDirect(0, c, 1, 1, dir);
searchDirect(L-1, c, -1, -1, counterDir);
}
for (int r = 1; r < L; r++)
{
searchDirect(r, 0, 1, 1, dir);
searchDirect(r, C-1, -1, -1, counterDir);
}
dir = ‘F‘, counterDir = ‘B‘;
for (int c = 0; c < C; c++)
{
searchDirect(L-1, c, -1, 1, dir);
searchDirect(0, c, 1, -1, counterDir);
}
for (int r = 0; r < L; r++)
{
searchDirect(r, 0, -1, 1, dir);
searchDirect(r, C-1, 1, -1, counterDir);
}
}
int main()
{
Trie = &gPool[0];
while (scanf("%d %d %d", &L, &C, &W) != EOF)
{
clearNode(Trie);
gPoolId = 1;
getchar();
for (int i = 0; i < L; i++)
{
gets(board[i]);
}
for (int i = 0; i < W; i++)
{
gets(word);
insertTrie(word, i);
}
buildFail();
searchAll();
for (int i = 0; i < W; i++)
{
printf("%d %d %c\n", gIndices[i][0], gIndices[i][1], gDir[i]);
}
}
return 0;
}
POJ 1204 Word Puzzles AC自己主动机题解
标签:class return r++ size watch tin uil inline direct
原文地址:http://www.cnblogs.com/jzdwajue/p/6829954.html