题目链接: poj 1204
题目大意: 给出字典,再给出n个单词
找出这些单词在单词表的什么位置,以什么顺序排放(8个方向,A表示正北,顺时针方向依次为B ~ H)
解题思路: 由于字典太大,若以字典的所有单词建立字典树空间复杂度很高
建立n个单词的字典树和失败指针
对字典的八个方向枚举,枚举每一个起点,根据AC字典树的特性
只需要行枚举(第一列和最后一列)和列枚举(第一行和最后一行)
代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 1003 struct snode{ int w,fail; int next[26]; }Tree[MAX*500]; struct node{ int x,y,fx; }ans[MAX]; int n,m,Index,listb[MAX*MAX],Fx[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}}; char ch1[MAX*2]; int ch1len[MAX],Map[MAX][MAX]; void Insert(int Star,int Tlen,int k) //建立字典树 { int i,S=Star,child; for(i=1;i<=Tlen;i++) { child=ch1[i-1]-'A'; if(Tree[S].next[child]==-1) { if(i==Tlen) Tree[Index].w=k; Tree[S].next[child]=Index++; } else if(i==Tlen) { Tree[Tree[S].next[child]].w=k; } S=Tree[S].next[child]; } } void Build_fail(int Star) //建立失败指针 { int i,e,s,temp,now_fail; s=e=0; listb[s++]=Star; while(s!=e) { temp=listb[e++]; for(i=0;i<26;i++) { if(Tree[temp].next[i]!=-1) { now_fail=Tree[temp].fail; while(now_fail!=-1) //***!=-1 { if(Tree[now_fail].next[i]!=-1) { Tree[Tree[temp].next[i]].fail=Tree[now_fail].next[i]; break; } now_fail=Tree[now_fail].fail; } if(now_fail==-1) { Tree[Tree[temp].next[i]].fail=0; } listb[s++]=Tree[temp].next[i]; } } } } int Ac_auto(int x,int y,int fx) //BFS匹配 { int i=0,p=0,temp,tempx,tempy,child,sum=0; while(1) { tempx=x+Fx[fx][0]*i; tempy=y+Fx[fx][1]*i; if(tempx<0||tempx>=n||tempy<0||tempy>=m) break; child=Map[tempx][tempy]; while(Tree[p].next[child]==-1&&p!=0) { p=Tree[p].fail; } p=(Tree[p].next[child]==-1)?0:Tree[p].next[child]; temp=p; while(Tree[temp].w!=-1&&temp!=0) { if(ans[Tree[temp].w].x==-1) { sum++; ans[Tree[temp].w].x=tempx; ans[Tree[temp].w].y=tempy; ans[Tree[temp].w].fx=fx; } temp=Tree[temp].fail; } i++; } return sum; } int main() { int k,i,j,j1,num; scanf("%d%d%d",&n,&m,&k); Index=1;num=0; memset(Map,-1,sizeof(Map)); memset(ans,-1,sizeof(ans)); memset(Tree,-1,sizeof(Tree)); for(i=0;i<n;i++) { scanf("%s",ch1); for(j=0;j<m;j++) { Map[i][j]=ch1[j]-'A'; } } for(i=1;i<=k;i++) { scanf("%s",ch1); ch1len[i]=strlen(ch1); Insert(0,ch1len[i],i); } Build_fail(0); for(i=0;i<n&&num<k;i++) //行扫描 { for(j1=0;j1<8&&num<k;j1++) { num+=Ac_auto(i,0,j1); num+=Ac_auto(i,m-1,j1); } } for(j=0;j<m&&num<k;j++) //列扫描 { for(j1=0;j1<8&&num<k;j1++) { num+=Ac_auto(n-1,j,j1); num+=Ac_auto(0,j,j1); } } for(i=1;i<=k;i++) { printf("%d %d %c\n",ans[i].x-(Fx[ans[i].fx][0]*(ch1len[i]-1)),ans[i].y-(Fx[ans[i].fx][1]*(ch1len[i]-1)),ans[i].fx+'A'); } return 0; }