/**
题目:pku1204 Word Puzzles
链接:http://poj.org/problem?id=1204
题意:给定一个L C(C <= 1000, L <= 1000)的字母矩阵,
再给定W(W <= 1000)个字符串,保证这些字符串都会在字母矩阵中出现(8种方向),
求它们的出现位置和方向。
思路:将单词构成ac自动机,然后对矩阵字符串从8个方向跑ac自动机,
向下方向:所有的(0,i) (0<=i<sm)为起点,一直跑到最下面。
其他方向类推;
注意:由于在自动机上找到的位置是单词的末尾位置,要回溯单词长度去找起点位置。
为了方便,逆向插入单词构造自动机,那么当前找到结尾位置的(x,y)就是起点了。方向也是反向的。 本题还可以字典树做法:
单词构造字典树。
枚举每一个(i,j)从它往八个方向分别跑字典树。好的数据会时间卡掉。 AC自动机好文章:http://www.cppblog.com/menjitianya/archive/2014/07/10/207604.html
*/ //#include<bits/stdc++.h>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define P pair<int,int>
#define ms(x,y) memset(x,y,sizeof x)
#define LL long long
const int maxn = ;
const int mod = 1e9+;
const int maxnode = maxn*maxn;
const int sigma_size = ;
struct node
{
int x, y, dir;
}ans[maxn];
int dir[][] = {{-,},{-,},{,},{,},{,},{,-},{,-},{-,-}};
char s[maxn][maxn];
int sn, sm;
struct AhoCorasickAutomata
{
int ch[maxnode][sigma_size];
int val[maxnode];
int sz;
int f[maxnode];
int last[maxnode];
void clear(){sz = ; memset(ch[],,sizeof ch[]); }
int idx(char c){return c-'A'; } void insert(char *s,int x)
{
int u = , n = strlen(s);
for(int i = ; i < n; i++){
int c = idx(s[i]);
if(!ch[u][c]){
memset(ch[sz], , sizeof ch[sz]);
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = x;
} void find(int x,int y,int f){
int j = ;
while(x>=&&x<sn&&y>=&&y<sm){
int c = idx(s[x][y]);
j = ch[j][c];
if(val[j]) print(j,x,y,f);
else if(last[j]) print(last[j],x,y,f);
x = x+dir[f][];
y = y+dir[f][];
}
} void print(int j,int x,int y,int dir)
{
if(j){
//cnt[val[j]]++;
ans[val[j]].x = x, ans[val[j]].y = y;
ans[val[j]].dir = dir;
print(last[j],x,y,dir);
}
} void getFail(){
queue<int> q;
f[] = ;
for(int c = ; c < sigma_size; c++){
int u = ch[][c];
if(u){f[u] = ; q.push(u); last[u] = ;}
} while(!q.empty()){
int r = q.front(); q.pop();
for(int c = ; c < sigma_size; c++){
int u = ch[r][c];
if(!u){
ch[r][c] = ch[f[r]][c]; continue;
}//if(!u) continue;
q.push(u);
int v = f[r];
while(v&&!ch[v][c]) v = f[v];
f[u] = ch[v][c];
last[u] = val[f[u]] ? f[u] : last[f[u]];
}
}
} } ac ;
char t[maxn];
int main()
{
int w;
while(scanf("%d%d%d",&sn,&sm,&w)!=EOF)
{
for(int i = ; i < sn; i++) scanf("%s",s[i]);
ac.clear();
for(int i = ; i <= w; i++){
scanf("%s",t);
reverse(t,t+strlen(t));///逆向插入,这样当查询的时候,当前的x,y就是起点。而不用回溯获取找起点。
///同理,方向的最终结果也要反向再输出。
ac.insert(t,i);
}
ac.getFail();
for(int i = ; i < sm; i++){
ac.find(,i,);///向下
ac.find(sn-,i,);///向上
ac.find(,i,);///向左下
ac.find(,i,);///向右下
ac.find(sn-,i,);///向右上
ac.find(sn-,i,);///向左上
}
for(int i = ; i < sn; i++){
ac.find(i,,);///向右
ac.find(i,sm-,);///向左
ac.find(i,,);///右下
ac.find(i,,);///右上
ac.find(i,sm-,);///左下
ac.find(i,sm-,);///左上
}
for(int i = ; i <= w; i++){
printf("%d %d %c\n",ans[i].x,ans[i].y,(ans[i].dir+)%+'A');
}
}
return ;
} /* */

pku1204 Word Puzzles AC自动机 二维字符串矩阵8个方向找模式串的起点坐标以及方向 挺好的!的更多相关文章

  1. UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )

    题目: 传送门 题意: 给你一个 n * m 的文本串 T, 再给你一个 r * c 的模式串 S: 问模式串 S 在文本串 T 中出现了多少次. 解: 法一: AC自动机 (正解) 670ms 把模 ...

  2. PKU 1204 Word Puzzles(AC自动机)

    题目大意:原题链接 给定一个字符串矩阵和待查找的单词,可以朝8个不同的方向查找,输出待查找单词第一个字母在矩阵中出现的位置和该单词被查到的方向. A~H代表8个不同的方向,A代表正北方向,其他依次以4 ...

  3. [poj] 1204 Word Puzzles || AC自动机

    原题 给个X*Y的字符串矩阵,W个询问,对每个询问输出这个串出现的位置及方向,共有8个方向,顺时针开始分别用A~H表示 AC自动机的板子题. 对于待匹配串建一个自动机,然后从矩阵的四周分别沿八个方向跑 ...

  4. UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher

    就向书上说得那样,如果模式串P的第i行出现在文本串T的第r行第c列,则cnt[r-i][c]++; 还有个很棘手的问题就是模式串中可能会有相同的串,所以用repr[i]来记录第i个模式串P[i]第一次 ...

  5. AC自动机(二维) UVA 11019 Matrix Matcher

    题目传送门 题意:训练指南P218 分析:一行一行的插入,一行一行的匹配,当匹配成功时将对应子矩阵的左上角位置cnt[r][c]++;然后统计 cnt[r][c] == x 的数量 #include ...

  6. 【AC自动机】【字符串】【字典树】AC自动机 学习笔记

    blog:www.wjyyy.top     AC自动机是一种毒瘤的方便的多模式串匹配算法.基于字典树,用到了类似KMP的思维.     AC自动机与KMP不同的是,AC自动机可以同时匹配多个模式串, ...

  7. 2018/7/31-zznuoj-问题 A: A + B 普拉斯【二维字符串+暴力模拟+考虑瑕疵的题意-0的特例】

    问题 A: A + B 普拉斯 在计算机中,数字是通过像01像素矩阵来显示的,最终的显示效果如下:  现在我们用01来构成这些数字 当宝儿姐输入A + B 时(log10(A)<50,log10 ...

  8. URAL - 1486 二维字符串HASH

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1486 题意:给定一个n*m的字符矩阵,问你是否存在两个不重合(可以有交集)的正方形矩阵完 ...

  9. 计算机二级-C语言-程序填空题-190109记录-对二维字符串数组的处理

    //给定程序,函数fun的功能是:求出形参ss所指字符串数组中最长字符串的长度,将其余字符串右边用字符*补齐,使其与最长的字符串等长.ss所指字符串数组中共有M个字符串,且串长<N. //重难点 ...

随机推荐

  1. ubuntu 安装ssh 服务

    百度地址: http://jingyan.baidu.com/article/00a07f38a5c05482d128dc5f.html

  2. AME_AME审批中子元素的概念和用途(概念)

    2014-05-30 Created By BaoXinjian AME: Oracle Approvals Management AME的6个元素的概念和主要作用: Attribue  ->  ...

  3. Python hypot() 函数

    描述 hypot() 返回欧几里德范数 sqrt(x*x + y*y). 语法 以下是 hypot() 方法的语法: import math math.hypot(x, y) 注意:hypot()是不 ...

  4. android动画具体解释一 概述

    动画和图形概述 Android 提供了大量的强大的API以应用于UI动画和绘制2D和3D图形.以下各节向你描写叙述了这些API的预览和系统能力以帮助你决定怎么才是达到你需求的最佳方法. 动画 Andr ...

  5. STM32 SPI接口的NSS引脚

    SPI_NSS 设置 NSS 信号由硬件( NSS 管脚)还是软件控制,这里我们一般通过软件控制 NSS ,而不是硬件自动控制,所以选择 SPI_NSS_Soft 选择了软件NSS之后,引脚NSS就可 ...

  6. ThreadLocal 类说明

    1 ThreadLocal 不是一个线程,而是保存线程本地化对象的容器.当运行于多线程环境的某个对象使用 ThreadLocal 维护变量时,ThreadLocal 为每一个使用该变量的线程分配一个独 ...

  7. ev3dev:c语言开发lego ev3主机

    有了ev3dev,真是一且皆有可能啊,最近,看到一个好人,居然做了一个ev3的c库. 激动中... 学习有目标了...,赶紧记录一下. https://github.com/theZiz/ev3c

  8. iptables控制较复杂案例

    场景设定: 管理员:192.168.101.80 公司有三个部门: 工程部:192.168.2.21-192.168.2.20 软件部门:192.168.2.21-192.168.2.30 经理办公室 ...

  9. Hg(Mercurial)版本管理学习

    1.关闭分支,首先切到你要关闭的分支 hg commit --close-branch -m. 2.仓库ip地址改变之后,重设仓库ip 找到.hg文件夹 - hgrc文件 - 记事本打开重设 3.推分 ...

  10. 2014年百度之星资格赛第四题Labyrinth

    Problem Description 度度熊是一仅仅喜欢探险的熊.一次偶然落进了一个m*n矩阵的迷宫.该迷宫仅仅能从矩阵左上角第一个方格開始走.仅仅有走到右上角的第一个格子才算走出迷宫,每一次仅仅能 ...