POJ1204 Word Puzzles(AC自动机)
给一个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自动机)的更多相关文章
- pku1204 Word Puzzles AC自动机 二维字符串矩阵8个方向找模式串的起点坐标以及方向 挺好的!
/** 题目:pku1204 Word Puzzles 链接:http://poj.org/problem?id=1204 题意:给定一个L C(C <= 1000, L <= 1000) ...
- PKU 1204 Word Puzzles(AC自动机)
题目大意:原题链接 给定一个字符串矩阵和待查找的单词,可以朝8个不同的方向查找,输出待查找单词第一个字母在矩阵中出现的位置和该单词被查到的方向. A~H代表8个不同的方向,A代表正北方向,其他依次以4 ...
- [poj] 1204 Word Puzzles || AC自动机
原题 给个X*Y的字符串矩阵,W个询问,对每个询问输出这个串出现的位置及方向,共有8个方向,顺时针开始分别用A~H表示 AC自动机的板子题. 对于待匹配串建一个自动机,然后从矩阵的四周分别沿八个方向跑 ...
- poj1204 Word Puzzles
Word Puzzles Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 12090 Accepted: 4547 S ...
- POJ 1204 Word Puzzles | AC 自动鸡
题目: 给一个字母矩阵和几个模式串,矩阵中的字符串可以有8个方向 输出每个模式串开头在矩阵中出现的坐标和这个串的方向 题解: 我们可以把模式串搞成AC自动机,然后枚举矩阵最外围一层的每个字母,向八个方 ...
- 【 POJ - 1204 Word Puzzles】(Trie+爆搜|AC自动机)
Word Puzzles Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 10782 Accepted: 4076 Special ...
- [POJ 1204]Word Puzzles(Trie树暴搜&AC自己主动机)
Description Word puzzles are usually simple and very entertaining for all ages. They are so entertai ...
- POJ 题目1204 Word Puzzles(AC自己主动机,多个方向查询)
Word Puzzles Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 10244 Accepted: 3864 S ...
- poj1204之AC自动机
Word Puzzles Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 8235 Accepted: 3104 Sp ...
随机推荐
- 给定一个值S,在有序数组中找出两个元素A和B,使 A+B = S.
在网上看到过一个面试题,感觉挺有意思,看别人的代码写的逻辑不够谨慎,重写了一个,较真了又... package com.array7.algorithm; public class Algorithm ...
- [Effective JavaScript 笔记]第21条:使用apply方法通过不同数量的参数调用函数
apply()方法定义 函数的apply()方法和call方法作用相同,区别在于接收的参数的方式不同.apply()方法接收两个参数,一个是对象,一个是参数数组. apply()作用 1.用于延长函数 ...
- [Effective JavaScript 笔记]第62条:在异步序列中使用嵌套或命名的回调函数
异步程序的操作顺序 61条讲述了异步API如何执行潜在的代价高昂的I/O操作,而不阻塞应用程序继续处理其他输入.理解异步程序的操作顺序刚开始有点混乱.例如,下面的代码会在打印"finishe ...
- storyboard和xib的各种问题
1.prepareFoSegue注意问题使用该方法设置的值, 必须要 viewWillApear之后用 2.storayboard的使用autolayout, constant = -16, 刚好在f ...
- Linux EOF使用
# cat << EOF > fileB 用法 例: vi ceshi.sh cat<<eof>file1 aaaa bbbb cccc dddd eof 操作 ...
- FOJ 1075
#include<stdio.h> #include<iostream> using namespace std; ]={,}; ]={}; void func() { ,fl ...
- NYOJ 38布线问题
http://acm.nyist.net/JudgeOnline/problem.php?pid=38 布线问题 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 南阳 ...
- HDOJ 1590
#include<stdio.h> #include<iostream> #include<stdlib.h> #include<string.h> u ...
- mysql将int 时间类型格式化
摘要 DATE_FORMAT(date,format) 根据format字符串安排date值的格式. DATE_FORMAT(date,format) 根据format字符串安排date值的格式. ...
- dhcp原理、安装、相关命令、疑惑
转自: http://blog.sina.com.cn/s/blog_642e41c20101tct3.html