您的位置:首页 > 其它

【POJ1204】Word Puzzles-AC自动机

2017-04-04 11:06 453 查看
测试地址:Word Puzzles

题目大意:在一个填满大写字母的N*M棋盘内找到询问的W个单词,输出出现点坐标和方向(方向从“向上为A”顺时针依次定义,如向右上为B,向右为C......)。

做法:对所有待查字符串构建AC自动机,然后对每个方向查找一遍棋盘即可求出答案。注意下标从0开始。

以下是本人代码(由于我一开始没注意,所以处理过程中下标是从1开始的,所以到输出的时候坐标减去了1):

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int n,m,q,rt,tot=0,len;
int fail[1000010],ch[1000010][30],id[1000010]={0},fa[1000010],ans[1010][3];
int dep[1000010];
char puz[1010][1010],s[1010];

void newnode(int &v)
{
v=++tot;
for(int i=0;i<=25;i++) ch[tot][i]=0;
}

void insert(int &v,int c,int p)
{
if (c>len) return;
if (!v) newnode(v);
int x=s[c]-'A';
insert(ch[v][x],c+1,p);
if (ch[v][x]) fa[ch[v][x]]=v;
if (c==len) id[v]=p;
}

void calcfail()
{
queue<int> q;
dep[rt]=0;
for(int i=0;i<=25;i++)
if (ch[rt][i]) dep[ch[rt][i]]=1,q.push(ch[rt][i]),fail[ch[rt][i]]=rt;
while(!q.empty())
{
int v=q.front();q.pop();
for(int i=0;i<=25;i++)
if (ch[v][i])
{
int x=fail[v];
dep[ch[v][i]]=dep[v]+1;
while(!ch[x][i]&&fail[x]) x=fail[x];
if (ch[x][i]) fail[ch[v][i]]=ch[x][i];
else fail[ch[v][i]]=rt;
q.push(ch[v][i]);
}
}
}

void search(int x,int y,int dx,int dy,int mode,int v)
{
if (id[v])
{
int i=v;
while(fail[i])
{
if (id[i]) ans[id[i]][0]=x-dep[i]*dx,ans[id[i]][1]=y-dep[i]*dy,ans[id[i]][2]=mode;
i=fail[i];
}
}
if (x<1||x>n||y<1||y>m) return;
int xx=puz[x][y]-'A';
while(!ch[v][xx]&&fail[v]) v=fail[v];
if (ch[v][xx]) search(x+dx,y+dy,dx,dy,mode,ch[v][xx]);
else search(x+dx,y+dy,dx,dy,mode,v);
}

int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
scanf("%s",&puz[i][1]);
newnode(rt);
fail[rt]=0;
for(int i=1;i<=q;i++)
{
scanf("%s",s);
len=strlen(s);
insert(rt,0,i);
}

calcfail();
for(int i=1;i<=m;i++)
{
search(n,i,-1,0,0,rt);
search(n,i,-1,1,1,rt);
search(n,i,-1,-1,7,rt);
search(1,i,1,0,4,rt);
search(1,i,1,1,3,rt);
search(1,i,1,-1,5,rt);
}
for(int i=1;i<=n;i++)
{
search(i,1,0,1,2,rt);
search(i,1,1,1,3,rt);
search(i,1,-1,1,1,rt);
search(i,m,0,-1,6,rt);
search(i,m,1,-1,5,rt);
search(i,m,-1,-1,7,rt);
}

for(int i=1;i<=q;i++)
printf("%d %d %c\n",ans[i][0]-1,ans[i][1]-1,ans[i][2]+'A');

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: