POJ 1204(AC自动机)

原创 2012年03月31日 10:05:11
Word Puzzles
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 6543   Accepted: 2486   Special Judge

Description

Word puzzles are usually simple and very entertaining for all ages. They are so entertaining that Pizza-Hut company started using table covers with word puzzles printed on them, possibly with the intent to minimise their client's perception of any possible delay in bringing them their order.

Even though word puzzles may be entertaining to solve by hand, they may become boring when they get very large. Computers do not yet get bored in solving tasks, therefore we thought you could devise a program to speedup (hopefully!) solution finding in such puzzles.

The following figure illustrates the PizzaHut puzzle. The names of the pizzas to be found in the puzzle are: MARGARITA, ALEMA, BARBECUE, TROPICAL, SUPREMA, LOUISIANA, CHEESEHAM, EUROPA, HAVAIANA, CAMPONESA.

Your task is to produce a program that given the word puzzle and words to be found in the puzzle, determines, for each word, the position of the first letter and its orientation in the puzzle.

You can assume that the left upper corner of the puzzle is the origin, (0,0). Furthemore, the orientation of the word is marked clockwise starting with letter A for north (note: there are 8 possible directions in total).

Input

The first line of input consists of three positive numbers, the number of lines, 0 < L <= 1000, the number of columns, 0 < C <= 1000, and the number of words to be found, 0 < W <= 1000. The following L input lines, each one of size C characters, contain the word puzzle. Then at last the W words are input one per line.

Output

Your program should output, for each word (using the same order as the words were input) a triplet defining the coordinates, line and column, where the first letter of the word appears, followed by a letter indicating the orientation of the word according to the rules define above. Each value in the triplet must be separated by one space only. 

这是我做的第二道AC自动机的题(第一道是HD2222)。。没想到能1Y。。舒坦。。。我是分方向分横纵枚举。。。

#include<stdio.h>
#include<string.h>

#define maxn 1000001
#define maxn2 1002
#define maxn3 100
#define maxn4 2000000
#define kind 26
#define clear(a,b) memset(a,b,sizeof(a))

const int di[8][2] = {{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
const char tranf[8] = {'E','F','G','H','A','B','C','D'};

char ma[maxn2][maxn2];
int X[maxn2],Y[maxn2],dir[maxn2];

struct AC_node{
  int a,b;
  struct AC_node *next[kind],*fail;
  AC_node(){
    fail = NULL;
    a = 0;
    b = 0;
    clear(next,NULL);
    }
  } *q[maxn];

char s1[maxn3],txt[maxn4];

void AC_trie(struct AC_node *T,char s[],int t)
{
  int k,i = strlen(s)-1;
  struct AC_node *op = T;
  while(i >= 0) {
    k = s[i] - 'A';
    if (op->next[k] == NULL) op->next[k] = new AC_node();
    op = op->next[k];
    i--;
    }
    op->a++;
    op->b = t;
}

void AC_build(struct AC_node *T)
{
  int i,h = 0,t = 0;
  struct AC_node *op,*tt;
  clear(q,NULL);
  T->fail = NULL;
  q[t++] = T;
  while (h < t) {
    op = q[h++];
    for(i = 0;i < kind;i++) {
      if (op->next[i]!=NULL) {
        if (op == T) op->next[i]->fail = T;
          else {
            tt = op->fail;
            while(tt != NULL) {
              if (tt->next[i] != NULL) {
                op->next[i]->fail = tt->next[i];
                break;
                }
              tt = tt->fail;
              }
            if (tt == NULL) op->next[i]->fail = T;
            }
        q[t++] = op->next[i];
        }
      }
    }
}

int AC_query(struct AC_node *T,int x,int y,int d)
{
  int i = 0,ans = 0,k;
  struct AC_node *op = T;
  while(ma[x][y]) {
    k = ma[x][y] - 'A';
    while(op->next[k] == NULL && op != T) op = op->fail;
    op = op->next[k];
    op = (op == NULL)?T:op;
    struct AC_node *tmp = op;
    while(tmp != T) {
      if (tmp->a > 0) {
        if (x < X[tmp->b] || (x == X[tmp->b] && y < Y[tmp->b])) {
          X[tmp->b] = x;
          Y[tmp->b] = y;
          dir[tmp->b] = d;
          }
        }
      tmp = tmp->fail;
      }
    x+=di[d][0];
    y+=di[d][1];
    }
  return ans;
}

int main()
{
  int j,m,n,i,k;

  scanf("%d%d%d",&m,&n,&k);
  clear(ma,0);
  getchar();
  for(i = 1;i <= m;i++,getchar())
    for(j = 1;j <= n;j++) scanf("%c",&ma[i][j]);
  struct AC_node *root = new AC_node();
  for(i = 1;i <= k;i++) {
      X[i] = maxn;
      Y[i] = maxn;
      scanf("%s",s1);
      AC_trie(root,s1,i);
    }
  AC_build(root);
  for(i = 1;i <= m;i++) {AC_query(root,i,1,2);AC_query(root,i,n,6);}
  for(i = 1;i <= n;i++) {AC_query(root,1,i,4);AC_query(root,m,i,0);}
  for(i = 1;i <= n;i++) {AC_query(root,1,i,3);AC_query(root,1,i,5);AC_query(root,m,i,7);AC_query(root,m,i,1);}
  for(i = 1;i <= m;i++) {AC_query(root,i,1,1);AC_query(root,i,1,3);AC_query(root,i,n,5);AC_query(root,i,n,7);}
  for(i = 1;i <= k;i++) printf("%d %d %c\n",X[i]-1,Y[i]-1,tranf[dir[i]]);
  return 0;
}


POJ 1204 AC自动机

点击打开链接 题意:给个L*C的字符串矩阵,W个询问,对每个询问输出这个串第一次出现的位置及方向,共有8个方向,用A~H表示 思路:用AC自动机进行快速匹配,细节处理特别多,不看题解的话应该会WA...
  • Dan__ge
  • Dan__ge
  • 2016年05月16日 20:22
  • 3906

POJ3691 - AC自动机的第一道DP

第一道AC自动机...从上周日就开始写了..搞得我都要抓狂了...今天也是看了在网上搜了些解题报告才搞定...发现和我自己整得差别较大...瞎忙活了3天...    .题意是说给了N个带病毒的DNA...
  • kk303
  • kk303
  • 2011年11月02日 19:38
  • 1892

POJ1204--Word Puzzles--AC自动机

Description Word puzzles are usually simple and very entertaining for all ages. They are so enter...
  • a305657
  • a305657
  • 2014年03月14日 19:27
  • 835

AC自动机+矩阵快速幂 HDU 2243

做这个题之前最好做一下POJ 2278(题解) 在POJ2278的基础上, 最终的答案就是26^1+26^2+......+26^L减去A^1+A^2+....+A^L 我们构造这么一个矩阵 |A...
  • Runner__
  • Runner__
  • 2016年05月13日 13:00
  • 365

POJ2778 AC自动机经典题

AC自动机模板题
  • WT_cnyali
  • WT_cnyali
  • 2017年04月09日 22:20
  • 283

poj 1204 AC自动机

最直观的想法是8*(n*n)*n*n暴力 由于在表里面要朝8个方向走,不能在上面建自动机,所以要在pattern建自动机 建好后,在原表上朝8个方向走遍历整个表,这时候复杂度是8*n*n 比较慢...
  • Jackyguo1992
  • Jackyguo1992
  • 2013年09月18日 12:58
  • 636

poj 1204 (AC自动机)

#include #include #include #include #include #include #include #include #include #include ...
  • dlut_ju
  • dlut_ju
  • 2013年08月13日 22:05
  • 586

POJ 1204 【AC自动机】

开始wa掉了,360行的代码找错真难受!!!居然是一个地方多减了一个1…… #include #include #include #include #include #include #includ...
  • zz_1215
  • zz_1215
  • 2012年05月14日 19:44
  • 447

POJ 1204 AC自动机的初步认识+模板题

前一向在搞字典树就是为了搞AC自动机...AC自动机的用处..或者说最一般的用处就是给一个字典..找一篇文章中哪些单词出现过的一种较优的方法...而AC自动机的结构或者说方法简单的说就是字典树+KMP...
  • kk303
  • kk303
  • 2011年10月27日 23:53
  • 3371

POJ 3691:DNA repair(AC自动机+DP)

DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 3353   Acc...
  • wugj03
  • wugj03
  • 2011年09月09日 11:55
  • 2197
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ 1204(AC自动机)
举报原因:
原因补充:

(最多只允许输入30个字)