Word Puzzles
字典树实现
题意:给一个l*c的字母矩阵,给一些单吃,去这个矩阵中找出这些单词的起始位置以及方向,方向按顺时针走,从上开始,分别用A,B,C...表示有8个方向。
对ac自动机还是不熟悉啊,老是敲错。
有些人超时应该是因为,每个点都去搜一次,其实不用,只用每行每列搜就可以了。
/* * File: main.cpp * Author: Mi * * Created on 2011年4月20日, 下午2:57 */ #include <cstdlib> #include <stdio.h> #include <string.h> #include <algorithm> #define KIND 26 #define MAX 1005 using namespace std; /* * */ char msg[MAX][MAX]; int d[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}},n,m; int ans[MAX][3],len[MAX]; bool ok(int x,int y) { return x>=0&&x<n&&y>=0&&y<m; } struct node { node *fail; node *next[KIND]; int num; node() { fail=NULL; memset(next,NULL,sizeof(next)); num=-1; } }*root,*que[MAX*MAX]; void Insert(node *root,char *str,int num) { node *p=root; for(int i=0;str[i];i++) { int Index=str[i]-'A'; if(p->next[Index]==NULL) p->next[Index]=new node(); p=p->next[Index]; } p->num=num; } void Build_AC_Automation(node *root) { int tail=0,head=0; que[head++]=root; root->fail=NULL; while(tail!=head) { node *cur=que[tail++]; for(int i=0;i<KIND;i++) if(cur->next[i]!=NULL) { if(cur==root) cur->next[i]->fail=root; else { node *ptr=cur->fail; while(ptr!=NULL) { if(ptr->next[i]!=NULL) { cur->next[i]->fail=ptr->next[i]; break; } ptr=ptr->fail; } if(ptr==NULL) cur->next[i]->fail=root; } que[head++]=cur->next[i]; } } } void AC_search(node *root,int x,int y,int k) { node *ptr=root; int xx=x,yy=y; while(ok(xx,yy)) { int Index=msg[xx][yy]-'A'; while(ptr->next[Index]==NULL&&ptr!=root) ptr=ptr->fail; ptr=ptr->next[Index]; if(ptr==NULL) ptr=root; node *temp=ptr; while(temp!=root&&temp->num!=-1) { ans[temp->num][0]=xx-len[temp->num]*d[k][0]; ans[temp->num][1]=yy-len[temp->num]*d[k][1]; ans[temp->num][2]=k; temp->num=-1; temp=temp->fail; } xx+=d[k][0]; yy+=d[k][1]; } } void solve() { int w; root=new node(); scanf("%d%d%d",&n,&m,&w); for(int i=0;i<n;i++) scanf("%s",msg[i]); for(int i=0;i<w;i++) { char str[MAX]; scanf("%s",str); Insert(root,str,i); len[i]=strlen(str)-1; } Build_AC_Automation(root); for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(i==0||j==0||i==n-1||j==m-1) for(int k=0;k<8;k++) AC_search(root,i,j,k); for(int i=0;i<w;i++) printf("%d %d %c/n",ans[i][0],ans[i][1],ans[i][2]+'A'); } int main(int argc, char** argv) { solve(); return 0; }