POJ1204 Word Puzzles

Word Puzzles
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 12319   Accepted: 4638   Special Judge

Description

Word puzzles are usually simple and very entertaining for all ages. They are so entertaining that Pizza-Hut company started using table covers with word puzzles printed on them, possibly with the intent to minimise their client's perception of any possible delay in bringing them their order. 

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

The first line of input consists of three positive numbers, the number of lines, 0 < L <= 1000, the number of columns, 0 < C <= 1000, and the number of words to be found, 0 < W <= 1000. The following L input lines, each one of size C characters, contain the word puzzle. Then at last the W words are input one per line.

Output

Your program should output, for each word (using the same order as the words were input) a triplet defining the coordinates, line and column, where the first letter of the word appears, followed by a letter indicating the orientation of the word according to the rules define above. Each value in the triplet must be separated by one space only.

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

题目描述

给出一个字母地图和一些字符串,请你找出每个字符串的第一个字母在地图中的位置和该字符串的方向。
假设地图左上角为原点(0,0)。可能的方向有8个,从北开始顺时针方向依次编号A~H,北方编号为“A”。

                         (字母地图)

           (方向)

输入格式

第一行包含三个正整数:L(0<L≤1000),C(0<C≤1000),W(0<W≤1000)。其中 L 表示地图的行数,C 表示地图的列数,W 表示字符串的数量。
接下来有 L 行、C 列,为字母地图。
接下来有 W 行,每行一个字符串。

输出格式

对于输入的每个单词串,你需要输出该字符串的第一个字母所在的行、列,以及字符串的方向。三个部分之间用一个空格间隔。
按输入的字符串顺序输出上述信息。


解析:

    解法一:

    Trie树暴搜,能够说是Trie模板题,将单词插入Trie树后,以地图上每一个点作为起点。8个方向搜索单词就可以,须要注意的就是当眼下的单词已经搜到尽头(终止节点),不要停止搜索!

    解法二:

    AC自动机。Trie树暴力的方法由于是从地图上每一个点开始搜。并且Trie树失配后就必须回到根节点又一次来过。所以复杂度太高,能够直接用AC自己主动机。利用AC自己主动机能够将字符串的后缀和模式串匹配的特点。从地图的四个边上的点作为起点,向八个方向匹配就可以,加之匹配过程中失配后能够沿着失败指针向上走,不必直接到根节点重头来,因此复杂度比第一种方法低不少。


AC自动机:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <queue>
using namespace std;

const int fx[10]={0,1,1,0,-1,-1,-1,0,1};
const int fy[10]={0,1,0,1,1,0,-1,-1,-1};
const int Max=1000010;
int p[Max];
int n,m,k,tot=1;
char ch[Max],map[1010][1010],dir[10]={'0','D','E','C','B','A','H','G','F'};
struct answer{int x,y,d;};
answer ans[1010];
struct shu{int son[30],fail,cnt,len;};
shu tree[Max];

inline void build(int flag)
{
   int position=1,len=strlen(ch+1);
   for(int i=1;i<=len;i++)
   {
   	 if(!tree[position].son[ch[i]-'A']) tree[position].son[ch[i]-'A']=++tot;
   	 position=tree[position].son[ch[i]-'A'];
   }
   tree[position].cnt=flag;
   tree[position].len=len;
}

inline void buildfail()
{
   int head=0,tail=1;
   memset(p,0,sizeof(p));
   p[1]=1;
   while(head < tail)
   {
   	 int u=p[++head],v,w;
   	 for(int i=0;i<26;i++)
   	 {
   	   v=tree[u].fail;
   	   while(!tree[v].son[i]) v=tree[v].fail;
   	   v=tree[v].son[i];w=tree[u].son[i];
   	   if(w) tree[w].fail=v,p[++tail]=w;
   	   else tree[u].son[i]=v;
   	 }
   }
}

inline void search(int x,int y,int q)
{
   int xx=x,yy=y,now=1;
   while((xx>=1) && (xx<=n) && (yy>=1) && (yy<=m))
   {
   	 now=tree[now].son[map[xx][yy]-'A'];
   	 int tmp=now;
   	 while(tmp)
   	 {
   	   if(tree[tmp].cnt)
	   {
	     ans[tree[tmp].cnt].x=xx-(tree[tmp].len-1)*fx[q]-1;
	     ans[tree[tmp].cnt].y=yy-(tree[tmp].len-1)*fy[q]-1;
	     ans[tree[tmp].cnt].d=q;
	   }
   	   tmp=tree[tmp].fail;
   	 }
   	 xx+=fx[q];yy+=fy[q];
   }
}

int main()
{
   //freopen("lx.in","r",stdin);
   //freopen("lx.out","w",stdout);

   for(int i=0;i<26;i++) tree[0].son[i]=1;

   scanf("%d%d%d\n",&n,&m,&k);
   for(int i=1;i<=n;i++)
   {
     for(int j=1;j<=m;j++)
       scanf("%c",&map[i][j]);
     scanf("\n");
   }
   for(int i=1;i<=k;i++)
   {
   	 scanf("%s\n",ch+1);
   	 build(i);
   }
   buildfail();

   for(int i=1;i<=n;i++)
     for(int j=1;j<=8;j++) search(i,1,j);
   for(int i=1;i<=n;i++)
     for(int j=1;j<=8;j++) search(i,m,j);
   for(int i=1;i<=m;i++)
     for(int j=1;j<=8;j++) search(1,i,j);
   for(int i=1;i<=m;i++)
     for(int j=1;j<=8;j++) search(n,i,j);

   for(int i=1;i<=k;i++) cout<<ans[i].x<<" "<<ans[i].y<<" "<<dir[ans[i].d]<<"\n";
   return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38083668/article/details/81004144