题目链接: 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;
}