/**
题目: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. Linux内核(3) - 分析内核源码如何入手(下)

    下面的分析,米卢教练说了,内容不重要,重要的是态度.就像韩局长对待日记的态度那样,严谨而细致. 只要你使用这样的态度开始分析内核,那么无论你选择内核的哪个部分作为切入点,比如USB,比如进程管理,在花 ...

  2. unity, 人物与移动跳台的交互

    ----更新(2015-7-1): 也可以用itween来移动跳台. ---- 例如人物跳到往复运动的移动跳台上后应随跳台运动. 要实现这个效果有两个思路,一是用运动学一是用动力学. 用动力学实现就是 ...

  3. 限制 nuget 更新包的版本号

    今天在搜索其它问题的时候,突然发现一个使用 nuget 的小技巧. 因为浏览器兼容性的问题,很多网站项目引用的 jQuery 组件版本需要保持在 2.0 以下,因为 2.0 以上需要现代浏览器的支持, ...

  4. android http post

    public static boolean postInfo(String info1, String info2, String info3, ....) { final HttpParams ht ...

  5. [hihoCoder] #1093 : 最短路径·三:SPFA算法

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 万圣节的晚上,小Hi和小Ho在吃过晚饭之后,来到了一个巨大的鬼屋! 鬼屋中一共有N个地点,分别编号为1..N,这N个地点之 ...

  6. Nginx用户认证配置方法详解(域名/目录)

    Nginx超级强大它可以单独为一个域名设置用户认证,方法也很简单我们只要生成用户认证的用户名和密码,然后再Nginx添加auth认证配置即可 Nginx可以为某一个域名单独加用户认证,具体做法如下: ...

  7. HTML5背景音乐的暂停与播放

    HTML代码:     <audio id="myaudio" loop="loop" preload="auto" autoplay ...

  8. 【Android】2.1 PhonewordApp—第1个Android应用程序

    分类:C#.Android.VS2015:  创建日期:2016-02-04 本例子演示如何添加一个简单的单页导航,在此基础上,再演示如何在第2个页面中显示第1个页面中拨打过的所有电话号码. (1)通 ...

  9. 【Android】6.3 ProgressDialog

    分类:C#.Android.VS2015: 创建日期:2016-02-08 一.简介 进度条对话框(ProgressDialog)常用于不能在短时间内快速完成的操作,显示进度条的目的是为了让用户明白程 ...

  10. 使用 NGINX 和 NGINX Plus 的 Ingress Controller 进行 Kubernetes 的负载均衡

    运行和管理跨机器集群的大规模的容器微服务应用是一个极具挑战的任务.Kubernetes 提供了一个强大的容器编排解决方案,从而帮助我们迎接这个挑战.它包含了一些重要特性,比如容错,自动伸缩,滚动升级, ...