• 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
    ",ansx[i]-1,ansy[i]-1,dir[d[i]]);
        return 0;
    }
    
  • 相关阅读:
    线程池中的scheduleAtFixedRate scheduleWithFixedDelay区别
    几道MySQL问题
    【SQL server 2012】复制数据库到另一台机器上
    LeetCode 98. 验证二叉搜索树
    深度学习知识点
    Graph Network Notes
    剑指 Offer 33. 二叉搜索树的后序遍历序列
    剑指 Offer 29. 顺时针打印矩阵
    LeetCode 54. 螺旋矩阵
    LeetCode 50. Pow(x, n)
  • 原文地址:https://www.cnblogs.com/mrsheep/p/7988920.html
Copyright © 2020-2023  润新知