【POJ1204】Word Puzzles-AC自动机

测试地址: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;
}


posted @ 2017-04-04 11:06  Maxwei_wzj  阅读(155)  评论(0编辑  收藏  举报