1. 程式人生 > >[poj] 1204 Word Puzzles || AC自動機

[poj] 1204 Word Puzzles || AC自動機

+= blog nsx else roo bfs poj ref r++

原題

給個X*Y的字符串矩陣,W個詢問,對每個詢問輸出這個串出現的位置及方向,共有8個方向,順時針開始分別用A~H表示

AC自動機的板子題。
對於待匹配串建一個自動機,然後從矩陣的四周分別沿八個方向跑,找到一個串的時候就記錄答案,但不能退出。

另:方向要找好啊!!

#include<cstdio>
#include<cstring>
#define N 1010
using namespace std;
int x,y,n,ansx[N],ansy[N],d[N],l[N];
//int dx[10]={0,0,1,1,1,0,-1,-1,-1},dy[10]={0,1,1,0,-1,-1,-1,0,1};
int dx[10]={0,-1,-1,0,1,1,1,0,-1},dy[10]={0,0,1,1,1,0,-1,-1,-1}; char t[N][N],s[N],r[10]=" ABCDEFGH"; struct hhh { int data; hhh *child[26],*fail; hhh() { fail=NULL; data=0; for (int i=0;i<26;i++) child[i]=NULL; } }; hhh *root=new hhh; hhh *now,*tmp; hhh* q[100
*1000+10]; void add(int x) { now=root; for (int i=1;i<=l[x];i++) { if (now->child[s[i]-'A']==NULL) now->child[s[i]-'A']=new hhh; now=now->child[s[i]-'A']; } now->data=x; } void bfs() { int l=0,r=0; root->fail=root; for
(int i=0;i<26;i++) { if (root->child[i]==NULL) root->child[i]=root; else root->child[i]->fail=root,q[r++]=(root->child[i]); } while (r!=l) { hhh* nw=q[l++]; for (int i=0;i<26;i++) { if (nw->child[i]) { now=nw->child[i]; if (now!=root) q[r++]=now; if (now->fail==NULL) now->fail=nw->fail->child[i]; } else nw->child[i]=nw->fail->child[i]; if (nw->data==0 && nw->fail->data) nw->data=nw->fail->data; } } } void find(int a,int b,int i) { now=root; while (1) { if (a<=0 || a>x) break; if (b<=0 || b>y) break; now=now->child[t[a][b]-'A']; tmp=now; while (tmp->data) { int tp=tmp->data; ansx[tp]=a-dx[i]*(l[tp]-1); ansy[tp]=b-dy[i]*(l[tp]-1); d[tp]=i; tmp=tmp->fail; } a+=dx[i]; b+=dy[i]; } } int main() { scanf("%d%d%d",&x,&y,&n); for (int i=1;i<=x;i++) scanf("%s",t[i]+1); for (int i=1;i<=n;i++) { scanf("%s",s+1); l[i]=strlen(s+1); add(i); } bfs(); for (int i=1;i<=8;i++) { for (int j=1;j<=x;j++) { find(j,1,i); find(j,y,i); } for (int j=1;j<=y;j++) { find(1,j,i); find(x,j,i); } } for (int i=1;i<=n;i++) printf("%d %d %c\n",ansx[i]-1,ansy[i]-1,r[d[i]]); return 0; }

[poj] 1204 Word Puzzles || AC自動機