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 ...
随机推荐
- cocos基础教程(4)基础概念介绍
在Cocos2d-x-3.x引擎中,采用节点树形结构来管理游戏对象,一个游戏可以划分为不同的场景,一个场景又可以分为不同的层,一个层又可以拥有任意个可见的游戏节点(即对象,游戏中基本上所有的类都派生于 ...
- 菜鸟带你飞______DP基础26道水题
DP 158:11:22 1205:00:00 Overview Problem Status Rank (56) Discuss Current Time: 2015-11-26 19:11:2 ...
- set_include_path详细解释
zendframework的示例index.php里有这样一句 set_include_path('.' . PATH_SEPARATOR . '../library/'. PATH_SEPARATO ...
- Word Pattern | & II
Word Pattern | Given a pattern and a string str, find if str follows the same pattern. Examples: pat ...
- net发送邮件
对于.NET而言,从2.0开始,发邮件已经是一件非常easy 的事了.下面我给出一个用C#群发邮件的实例,做了比较详细的注解,希望对有需要的朋友有所help.看了这篇BLOG,如果你还不会用.NET发 ...
- mybatis3 :insert返回插入的主键(selectKey)
Mysql: 主键自增长. 加上:keyProperty="id"就可以获得了. <insert id="insert" parameterType=&q ...
- Android 调用浏览器和嵌入网页
Android App开发时由于布局相对麻烦,很多时候一个App通常是由html5和原生控件相结合而成.简单的网页应用可以直接内嵌html5页面即可,对于需要调用复杂的底层功能时则采用原生控件的方式进 ...
- Java for LeetCode 150 Evaluate Reverse Polish Notation
Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...
- Greedy:Cleaning Shifts(POJ 2376)
牛的大扫除 题目大意:农夫有N只牛,这些牛要帮助打扫农舍,这些牛只能打扫固定位置(千万要注意这个位置不是连续的),每一段区间必须至少有一只牛打扫,问你至少需要多少只牛?(如果区间不能完全被覆盖,则 ...
- 越狱后天气闪退 iPhone5天气闪退解决方法
iPhone5天气闪退解决方法: 第一步:前往Cydia卸载AppSync; 第二步:通过iTools删除/var/mobile/Library/Caches/com.apple.mobile.ins ...