Time Limit: 5000MS | Memory Limit: 65536K | |||
Total Submissions: 6543 | Accepted: 2486 | Special Judge |
Description
Even though word puzzles may be entertaining to solve by hand, they may become boring when they get very large. Computers do not yet get bored in solving tasks, therefore we thought you could devise a program to speedup (hopefully!) solution finding in such puzzles.
The following figure illustrates the PizzaHut puzzle. The names of the pizzas to be found in the puzzle are: MARGARITA, ALEMA, BARBECUE, TROPICAL, SUPREMA, LOUISIANA, CHEESEHAM, EUROPA, HAVAIANA, CAMPONESA.
Your task is to produce a program that given the word puzzle and words to be found in the puzzle, determines, for each word, the position of the first letter and its orientation in the puzzle.
You can assume that the left upper corner of the puzzle is the origin, (0,0). Furthemore, the orientation of the word is marked clockwise starting with letter A for north (note: there are 8 possible directions in total).
Input
Output
#include<stdio.h>
#include<string.h>
#define maxn 1000001
#define maxn2 1002
#define maxn3 100
#define maxn4 2000000
#define kind 26
#define clear(a,b) memset(a,b,sizeof(a))
const int di[8][2] = {{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
const char tranf[8] = {'E','F','G','H','A','B','C','D'};
char ma[maxn2][maxn2];
int X[maxn2],Y[maxn2],dir[maxn2];
struct AC_node{
int a,b;
struct AC_node *next[kind],*fail;
AC_node(){
fail = NULL;
a = 0;
b = 0;
clear(next,NULL);
}
} *q[maxn];
char s1[maxn3],txt[maxn4];
void AC_trie(struct AC_node *T,char s[],int t)
{
int k,i = strlen(s)-1;
struct AC_node *op = T;
while(i >= 0) {
k = s[i] - 'A';
if (op->next[k] == NULL) op->next[k] = new AC_node();
op = op->next[k];
i--;
}
op->a++;
op->b = t;
}
void AC_build(struct AC_node *T)
{
int i,h = 0,t = 0;
struct AC_node *op,*tt;
clear(q,NULL);
T->fail = NULL;
q[t++] = T;
while (h < t) {
op = q[h++];
for(i = 0;i < kind;i++) {
if (op->next[i]!=NULL) {
if (op == T) op->next[i]->fail = T;
else {
tt = op->fail;
while(tt != NULL) {
if (tt->next[i] != NULL) {
op->next[i]->fail = tt->next[i];
break;
}
tt = tt->fail;
}
if (tt == NULL) op->next[i]->fail = T;
}
q[t++] = op->next[i];
}
}
}
}
int AC_query(struct AC_node *T,int x,int y,int d)
{
int i = 0,ans = 0,k;
struct AC_node *op = T;
while(ma[x][y]) {
k = ma[x][y] - 'A';
while(op->next[k] == NULL && op != T) op = op->fail;
op = op->next[k];
op = (op == NULL)?T:op;
struct AC_node *tmp = op;
while(tmp != T) {
if (tmp->a > 0) {
if (x < X[tmp->b] || (x == X[tmp->b] && y < Y[tmp->b])) {
X[tmp->b] = x;
Y[tmp->b] = y;
dir[tmp->b] = d;
}
}
tmp = tmp->fail;
}
x+=di[d][0];
y+=di[d][1];
}
return ans;
}
int main()
{
int j,m,n,i,k;
scanf("%d%d%d",&m,&n,&k);
clear(ma,0);
getchar();
for(i = 1;i <= m;i++,getchar())
for(j = 1;j <= n;j++) scanf("%c",&ma[i][j]);
struct AC_node *root = new AC_node();
for(i = 1;i <= k;i++) {
X[i] = maxn;
Y[i] = maxn;
scanf("%s",s1);
AC_trie(root,s1,i);
}
AC_build(root);
for(i = 1;i <= m;i++) {AC_query(root,i,1,2);AC_query(root,i,n,6);}
for(i = 1;i <= n;i++) {AC_query(root,1,i,4);AC_query(root,m,i,0);}
for(i = 1;i <= n;i++) {AC_query(root,1,i,3);AC_query(root,1,i,5);AC_query(root,m,i,7);AC_query(root,m,i,1);}
for(i = 1;i <= m;i++) {AC_query(root,i,1,1);AC_query(root,i,1,3);AC_query(root,i,n,5);AC_query(root,i,n,7);}
for(i = 1;i <= k;i++) printf("%d %d %c\n",X[i]-1,Y[i]-1,tranf[dir[i]]);
return 0;
}