POJ 1204 Word Puzzles | AC 自动鸡
题目:
给一个字母矩阵和几个模式串,矩阵中的字符串可以有8个方向
输出每个模式串开头在矩阵中出现的坐标和这个串的方向
题解:
我们可以把模式串搞成AC自动机,然后枚举矩阵最外围一层的每个字母,向八个方向进行匹配
代码中danger标记为判断这个节点是不是一个模式串的结尾,
这道题可以直接字符串反向构建AC自动机,匹配到的就是开头(代码是正向)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define Z 27
#define N 1010
using namespace std;
struct node
{
int trans[Z],fail,danger;
void init()
{
memset(trans,0,sizeof(trans));
danger=fail=0;
}
}tr[1000010];
char puzzle[N][N],s[N],dir[10]={'A','B','C','D','E','F','G','H'};
int l,c,w,dx[10]={-1,-1,0,1,1,1,0,-1},dy[10]={0,1,1,1,0,-1,-1,-1};
int fa[N],ansx[N],ansy[N],tot=1,len[N],d[N];
int find(int x)
{
return fa[x]=fa[x]==x?x:find(fa[x]);
}
void insert(char s[],int id)
{
int len=strlen(s+1),now=1;
for (int i=1;i<=len;i++)
{
if (tr[now].trans[s[i]-'A']==0)
tr[tr[now].trans[s[i]-'A']=++tot].init();
now=tr[now].trans[s[i]-'A'];
}
if (tr[now].danger)
fa[find(id)]=find(tr[now].danger);
else
tr[now].danger=id;
}
void BuildFail()
{
queue <int> q;
tr[1].fail=1;
for (int i=0;i<26;i++)
{
if (tr[1].trans[i]==0)
tr[1].trans[i]=1;
else
{
tr[tr[1].trans[i]].fail=1;
q.push(tr[1].trans[i]);
}
}
while (!q.empty())
{
int u=q.front(),v,w;
for (int i=0;i<26;i++)
{
v=tr[u].fail;
v=tr[v].trans[i],w=tr[u].trans[i];
if (w) tr[w].fail=v,q.push(w);
else tr[u].trans[i]=v;
}
q.pop();
if (tr[u].danger==0 && tr[tr[u].fail].danger)
tr[u].danger=tr[tr[u].fail].danger;
}
}
void query(int x,int y,int t)
{
int p=1;
while (x>0 && y>0 && x<=l && y<=c)
{
p=tr[p].trans[puzzle[x][y]-'A'];
int ap=p;
while (tr[ap].danger)
{
int k=tr[ap].danger;
ansx[k]=x-dx[t]*(len[k]-1);
ansy[k]=y-dy[t]*(len[k]-1);
d[k]=t;
ap=tr[ap].fail;
}
x+=dx[t];
y+=dy[t];
}
}
int main()
{
scanf("%d%d%d",&l,&c,&w);
for (int i=1;i<=l;i++)
scanf("%s",puzzle[i]+1);
for (int i=1;i<=w;i++)
{
scanf("%s",s+1);
fa[i]=i;
len[i]=strlen(s+1);
insert(s,i);
}
BuildFail();
for (int i=1;i<=l;i++)
for (int j=0;j<8;j++)
query(i,1,j),query(i,c,j);
for (int i=1;i<=c;i++)
for (int j=0;j<8;j++)
query(1,i,j),query(l,i,j);
for (int i=1;i<=w;i++)
printf("%d %d %c\n",ansx[i]-1,ansy[i]-1,dir[d[i]]);
return 0;
}

浙公网安备 33010602011771号