1. 程式人生 > >POJ 1204 Word Puzzles | AC 自動雞

POJ 1204 Word Puzzles | AC 自動雞

class 是不是 std can tran pty ace cst ++

題目:

給一個字母矩陣和幾個模式串,矩陣中的字符串可以有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;
}

POJ 1204 Word Puzzles | AC 自動雞