AC自动机的经典题
可以使用一个小技巧,将要查找的单词反过来建自动机,这样便于记录首字母的位置。
#include <iostream>
using namespace std;
const int maxn=1005,maxl=200000;
const int dx[9]={0,-1,-1,0,1,1,1,0,-1};
const int dy[9]={0,0,1,1,1,0,-1,-1,-1};
struct node
{
node* ch[26];
node* fail;
int no;
};
node* root=new node;
char s[maxn],a[maxn][maxn];
int gx[maxn],gy[maxn],ansx[maxn],ansy[maxn],ansd[maxn];
int i,j,k,dir,n,m,kk;
void ins(char* s,int x)
{
node* now=root;
int i,j,k,len=strlen(s);
for (i=len-1;i>=0;i--)
{
k=s[i]-'A';
if (now->ch[k]!=0)
now=now->ch[k];
else
{
now->ch[k]=new node;
now=now->ch[k];
for (int j=0;j<26;j++)
now->ch[j]=0;
now->no=-1;now->fail=root;
}
}
now->no=x;
}
node* q[maxl];
void build()
{
int i,h=0,r=1;
node *now,*ff;
root->fail=0;
q[++h]=root;
while (h<=r)
{
now=q[h++];
for (i=0;i<26;i++)
if (now->ch[i]!=0)
{
q[++r]=now->ch[i];
for (ff=now->fail;ff!=0;ff=ff->fail)
if (ff->ch[i]!=0)
{
now->ch[i]->fail=ff->ch[i];
break;
}
}
}
}
void match(char* s)
{
int i,j,k,len=strlen(s);
node* now=root,*tmp;
for (i=0;i<len;i++)
{
k=s[i]-'A';
while (now->ch[k]==0 && now!=root)
now=now->fail;
if (now->ch[k]==0) continue;
now=now->ch[k];
tmp=now;
while (tmp!=0 && tmp->no!=-1)
{
ansx[tmp->no]=gx[i];
ansy[tmp->no]=gy[i];
ansd[tmp->no]=dir;
tmp->no=-1;
tmp=tmp->fail;
}
}
}
void make(int x,int y,int dir)
{
int len=0;
while (x>=0 && x<n && y>=0 && y<m)
{
s[len]=a[x][y];
gx[len]=x;gy[len]=y;
x+=dx[dir];y+=dy[dir];
len++;
}
}
int main()
{
freopen("pin.txt","r",stdin);
freopen("pou.txt","w",stdout);
cin >> n >> m >> kk;
for (i=0;i<26;i++)
root->ch[i]=0;
root->no=-1;
getchar();
for (i=0;i<n;i++)
{
for (j=0;j<m;j++)
a[i][j]=getchar();
getchar();
}
for (i=0;i<kk;i++)
{
cin >> s;
ins(s,i);
}
build();
for (i=0;i<n;i++)
for (j=0;j<m;j++)
if (i==0 || i==n-1 || j==0 || j==m-1)
for (k=1;k<=8;k++)
{
if (k==4) make(i,j,8);
else make(i,j,(k+4)%8);
dir=k;
match(s);
}
for (i=0;i<kk;i++)
printf("%d %d %c\n",ansx[i],ansy[i],ansd[i]+'A'-1);
return 0;
}