给出一个字母地图和一些字符串,请你找出每个字符串的第一个字母在地图中的位置和该字符串的方向。
假设地图左上角为原点(0,0)。可能的方向有8个,从北开始顺时针方向依次编号A~H,北方编号为“A”。
(字母地图)
(方向)
Time Limit: 5000MS | Memory Limit: 65536K | |||
Total Submissions: 12319 | Accepted: 4638 | Special Judge |
Description
Input
Output
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;
}