给一个L*C字符矩阵和W个字符串,问那些字符串出现在矩阵的位置,横竖斜八个向。

就是个多模式匹配的问题,直接AC自动机搞了,枚举字符矩阵八个方向的所有字符串构成主串,然后在W个模式串构造的AC自动机上跑。

另外,temp指针的那个找遗漏后缀的过程执行时标记一下,下一次再到这个结点就不需要再进行一次temp的过程,这样的时间复杂度就是O(W个模式串总长+LC)。

一开始还想8个方向分别计算坐标= =写第二个方向懒得写了,然后就忽然想到可以一开始构造主串时就存坐标。。最后代码很是挺长的。。

 #include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define MAXN 111111
int tn,ch[MAXN][],flag[MAXN],fail[MAXN],len[MAXN];
void insert(char *s,int k,int l){
int x=;
for(int i=; s[i]; ++i){
int y=s[i]-'A';
if(ch[x][y]==) ch[x][y]=++tn;
x=ch[x][y];
}
flag[x]=k;
len[x]=l;
}
void getFail(){
memset(fail,,sizeof(fail));
queue<int> que;
for(int i=; i<; ++i){
if(ch[][i]) que.push(ch[][i]);
}
while(!que.empty()){
int x=que.front(); que.pop();
for(int i=; i<; ++i){
if(ch[x][i]) que.push(ch[x][i]),fail[ch[x][i]]=ch[fail[x]][i];
else ch[x][i]=ch[fail[x]][i];
}
}
} int n,m;
int ansx[],ansy[],anso[];
char str[]; int sx[],sy[];
void match(char o){
int x=;
for(int i=; str[i]; ++i){
int y=str[i]-'A';
x=ch[x][y];
int tmp=x;
while(flag[tmp] && tmp){
if(flag[tmp]>){
int &idx=flag[tmp];
ansx[idx]=sx[i-len[tmp]+];
ansy[idx]=sy[i-len[tmp]+];
anso[idx]=o;
idx=-;
}else if(flag[tmp]==-) break;
tmp=fail[tmp];
}
}
}
char map[][];
int main(){
int w;
scanf("%d%d%d",&n,&m,&w);
for(int i=; i<n; ++i) scanf("%s",map[i]);
for(int i=; i<=w; ++i){
scanf("%s",str);
insert(str,i,strlen(str));
}
getFail();
int sn;
//zero
for(int i=; i<m; ++i){
for(int j=; j<n; ++j){
sx[n-j-]=j; sy[n-j-]=i;
str[n-j-]=map[j][i];
}
str[n]=;
match('A');
}
//one
for(int i=; i<n; ++i){
int x=i,y=,sn=;
while(x>= && y<m){
sx[sn]=x; sy[sn]=y;
str[sn++]=map[x][y];
--x; ++y;
}
str[sn]=;
match('B');
}
for(int i=; i<m; ++i){
int x=n-,y=i,sn=;
while(x>= && y<m){
sx[sn]=x; sy[sn]=y;
str[sn++]=map[x][y];
--x; ++y;
}
str[sn]=;
match('B');
}
//two
for(int i=; i<n; ++i){
for(int j=; j<m; ++j){
sx[j]=i; sy[j]=j;
str[j]=map[i][j];
}
str[m]=;
match('C');
}
//three
for(int i=; i<m; ++i){
int x=,y=i,sn=;
while(x<n && y<m){
sx[sn]=x; sy[sn]=y;
str[sn++]=map[x][y];
++x; ++y;
}
str[sn]=;
match('D');
}
for(int i=; i<n; ++i){
int x=i,y=,sn=;
while(x<n && y<m){
sx[sn]=x; sy[sn]=y;
str[sn++]=map[x][y];
++x; ++y;
}
str[sn]=;
match('D');
}
//four
for(int i=; i<m; ++i){
for(int j=; j<n; ++j){
sx[j]=j; sy[j]=i;
str[j]=map[j][i];
}
str[n]=;
match('E');
}
//five
for(int i=; i<m; ++i){
int x=,y=i,sn=;
while(x<n && y>=){
sx[sn]=x; sy[sn]=y;
str[sn++]=map[x][y];
++x; --y;
}
str[sn]=;
match('F');
}
for(int i=; i<n; ++i){
int x=i,y=m-,sn=;
while(x<n && y>=){
sx[sn]=x; sy[sn]=y;
str[sn++]=map[x][y];
++x; --y;
}
str[sn]=;
match('F');
}
//six
for(int i=; i<n; ++i){
for(int j=; j<m; ++j){
sx[m-j-]=i; sy[m-j-]=j;
str[m-j-]=map[i][j];
}
str[m]=;
match('G');
}
//seven
for(int i=; i<m; ++i){
int x=n-,y=i,sn=;
while(x>= && y>=){
sx[sn]=x; sy[sn]=y;
str[sn++]=map[x][y];
--x; --y;
}
str[sn]=;
match('H');
}
for(int i=; i<n-; ++i){
int x=i,y=m-,sn=;
while(x>= && y>=){
sx[sn]=x; sy[sn]=y;
str[sn++]=map[x][y];
--x; --y;
}
str[sn]=;
match('H');
}
for(int i=; i<=w; ++i){
printf("%d %d %c\n",ansx[i],ansy[i],anso[i]);
}
return ;
}

POJ1204 Word Puzzles(AC自动机)的更多相关文章

  1. pku1204 Word Puzzles AC自动机 二维字符串矩阵8个方向找模式串的起点坐标以及方向 挺好的!

    /** 题目:pku1204 Word Puzzles 链接:http://poj.org/problem?id=1204 题意:给定一个L C(C <= 1000, L <= 1000) ...

  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. poj1204 Word Puzzles

    Word Puzzles Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 12090   Accepted: 4547   S ...

  5. POJ 1204 Word Puzzles | AC 自动鸡

    题目: 给一个字母矩阵和几个模式串,矩阵中的字符串可以有8个方向 输出每个模式串开头在矩阵中出现的坐标和这个串的方向 题解: 我们可以把模式串搞成AC自动机,然后枚举矩阵最外围一层的每个字母,向八个方 ...

  6. 【 POJ - 1204 Word Puzzles】(Trie+爆搜|AC自动机)

    Word Puzzles Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 10782 Accepted: 4076 Special ...

  7. [POJ 1204]Word Puzzles(Trie树暴搜&amp;AC自己主动机)

    Description Word puzzles are usually simple and very entertaining for all ages. They are so entertai ...

  8. POJ 题目1204 Word Puzzles(AC自己主动机,多个方向查询)

    Word Puzzles Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10244   Accepted: 3864   S ...

  9. poj1204之AC自动机

    Word Puzzles Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 8235   Accepted: 3104   Sp ...

随机推荐

  1. Ubuntu 开机自启动工具 update-rd.d 使用详解

    常用命令: $ sudo update-rc.d nginx defaults      #增加服务 $ sudo update-rc.d -f nginx remove    #移除服务 Linux ...

  2. ios5之后arc的问题

    原创: 自从ios5以后, apple官方引进了ARC (automaically reference count 自动索引计数) 这个新特性, 简单的说就是对象设置为nil(空引用)之后, 当自动索 ...

  3. HDOJ 1162

    Eddy's picture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  4. WCDMA是什么意思?CDMA是什么意思?GSM是什么意思

    有些朋友在购买3G智能手机的时候会遇到这样的困惑,为什么相同的手机会有不同手机网络制式之分呢?有的支持WCDMA/GSM,有的支持CDMA/GSM,到底自己应该选购哪一种手机好呢?WCDMA是什么意思 ...

  5. wget批量下载

    wget -i download.txt 这样就会把download.txt里面列出的每个URL都下载下来. wget -c http://the.url.of/incomplete/file 使用断 ...

  6. 【OpenStack】OpenStack系列12之OpenStack自动化测试详解

    参考文档: https://github.com/yongluo2013/osf-openstack-training/blob/master/installation/How-to-setup-op ...

  7. 《ASP.NET1200例》未能找到元数据文件解决办法

         今天在做一个项目的时候,遇到这样的一个问题,我用的是三层结构的.未能找到元数据文件“D:\SYSTEM\桌面\MyExam\MyExam\MyExamBLL\bin\Debug\BLL.dl ...

  8. Live Archive 3644 X-Plosives 解题报告

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=1 ...

  9. linux下重启tomcat、实时查看tomcat运行日志

    在Linux系统下,重启Tomcat使用命令操作的! 首先,进入Tomcat下的bin目录 cd /usr/local/tomcat/bin 使用Tomcat关闭命令 ./shutdown.sh 查看 ...

  10. August 3rd, 2016, Week 32nd, Wednesday

    I am looking for someone to share in an adventure. 我在找能和我一起分享冒险之旅的人. We are all looking for someone ...