• 【POJ1204】Word Puzzles-AC自动机


    测试地址:Word Puzzles

    题目大意:在一个填满大写字母的N*M棋盘内找到询问的W个单词,输出出现点坐标和方向(方向从“向上为A”顺时针依次定义,如向右上为B,向右为C......)。

    做法:对所有待查字符串构建AC自动机,然后对每个方向查找一遍棋盘即可求出答案。注意下标从0开始。

    以下是本人代码(由于我一开始没注意,所以处理过程中下标是从1开始的,所以到输出的时候坐标减去了1):

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    int n,m,q,rt,tot=0,len;
    int fail[1000010],ch[1000010][30],id[1000010]={0},fa[1000010],ans[1010][3];
    int dep[1000010];
    char puz[1010][1010],s[1010];
    
    void newnode(int &v)
    {
      v=++tot;
      for(int i=0;i<=25;i++) ch[tot][i]=0;
    }
    
    void insert(int &v,int c,int p)
    {
      if (c>len) return;
      if (!v) newnode(v);
      int x=s[c]-'A';
      insert(ch[v][x],c+1,p);
      if (ch[v][x]) fa[ch[v][x]]=v;
      if (c==len) id[v]=p;
    }
    
    void calcfail()
    {
      queue<int> q;
      dep[rt]=0;
      for(int i=0;i<=25;i++)
        if (ch[rt][i]) dep[ch[rt][i]]=1,q.push(ch[rt][i]),fail[ch[rt][i]]=rt;
      while(!q.empty())
      {
        int v=q.front();q.pop();
    	for(int i=0;i<=25;i++)
    	  if (ch[v][i])
    	  {
    	    int x=fail[v];
    		dep[ch[v][i]]=dep[v]+1;
    		while(!ch[x][i]&&fail[x]) x=fail[x];
    		if (ch[x][i]) fail[ch[v][i]]=ch[x][i];
    		else fail[ch[v][i]]=rt;
    	    q.push(ch[v][i]);
    	  }
      }
    }
    
    void search(int x,int y,int dx,int dy,int mode,int v)
    {
      if (id[v])
      {
        int i=v;
    	while(fail[i])
    	{
    	  if (id[i]) ans[id[i]][0]=x-dep[i]*dx,ans[id[i]][1]=y-dep[i]*dy,ans[id[i]][2]=mode;
          i=fail[i];
    	}
      }
      if (x<1||x>n||y<1||y>m) return;
      int xx=puz[x][y]-'A';
      while(!ch[v][xx]&&fail[v]) v=fail[v];
      if (ch[v][xx]) search(x+dx,y+dy,dx,dy,mode,ch[v][xx]);
      else search(x+dx,y+dy,dx,dy,mode,v);
    }
    
    int main()
    {
      scanf("%d%d%d",&n,&m,&q);
      for(int i=1;i<=n;i++)
        scanf("%s",&puz[i][1]);
      newnode(rt);
      fail[rt]=0;
      for(int i=1;i<=q;i++)
      {
        scanf("%s",s);
    	len=strlen(s);
    	insert(rt,0,i);
      }
      
      calcfail();
      for(int i=1;i<=m;i++)
      {
        search(n,i,-1,0,0,rt);
    	search(n,i,-1,1,1,rt);
    	search(n,i,-1,-1,7,rt);
        search(1,i,1,0,4,rt);
    	search(1,i,1,1,3,rt);
    	search(1,i,1,-1,5,rt);
      }
      for(int i=1;i<=n;i++)
      {
        search(i,1,0,1,2,rt);
    	search(i,1,1,1,3,rt);
    	search(i,1,-1,1,1,rt);
    	search(i,m,0,-1,6,rt);
    	search(i,m,1,-1,5,rt);
    	search(i,m,-1,-1,7,rt);
      }
      
      for(int i=1;i<=q;i++)
        printf("%d %d %c
    ",ans[i][0]-1,ans[i][1]-1,ans[i][2]+'A');
      
      return 0;
    }
    


  • 相关阅读:
    【已解决】对发现无理数过程的逻辑严谨性的疑惑
    微积分奇观之计算曲线的平均高度
    闲鱼二维码 另外那个号
    联通KD-YUN-811G光猫管理员密码
    人工智能结课作业-BP神经网络/卷积神经网络手写体识别
    人工智能结课作业-遗传算法/粒子群寻优/蚁群算法解决TSP问题
    人工智能结课作业-DFS/BFS/Astar解决八数码问题
    AMD 2020显卡驱动没有切换独立显卡选项
    linux创建文件夹快捷方式
    Ubuntu 18.04 设置开机启动脚本
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793747.html
Copyright © 2020-2023  润新知