题目大意;原题链接

给定一个字符串矩阵和待查找的单词,可以朝8个不同的方向查找,输出待查找单词第一个字母在矩阵中出现的位置和该单词被查到的方向.

A~H代表8个不同的方向,A代表正北方向,其他依次以45度角的方向顺时针增加.

解题思路:

解法一:Trie树暴搜

因为不查询重复单词,所以dfs(int u,int i,int j,int k)函数中当已经查询到单词时,val[u]可以置零做标记.

#include<cstdio>
#include<cstring>
#define maxn 200010
using namespace std;
bool vis[];
int n,m,w,x,y,sz=;//sz得为全局变量
char str[][],word[];
int val[maxn],out[][];
int dir[][]={-,,-,,,,,,,,,-,,-,-,-};//顺时针
struct Trie
{
int next[];
}trie[maxn]; void insert(char *s,int k)
{
int u=,len=strlen(s);
for(int i=;i<len;i++){
int id=s[i]-'A';
if(!trie[u].next[id])
trie[u].next[id]=sz++;
u=trie[u].next[id];
}
val[u]=k;//u为结点编号,k为单词编号
}
void dfs(int u,int i,int j,int k)//k记录方向
{
if(u==||i<||i>=n||j<||j>=m) return;//该语句之前放在if(val[u])条件之后,WA
if(val[u]){
out[val[u]][]=x;
out[val[u]][]=y;
out[val[u]][]=k;
val[u]=;//做标记,因为不查询重复单词
}
int id=str[i+dir[k][]][j+dir[k][]]-'A';
dfs(trie[u].next[id],i+dir[k][],j+dir[k][],k);//必须得朝同一方向搜索
} int main()
{
scanf("%d%d%d",&n,&m,&w);
for(int i=;i<n;i++)
scanf("%s",str[i]);
for(int i=;i<=w;i++){
scanf("%s",word);
insert(word,i);
vis[word[]-'A']=;
}
for(int i=;i<n;i++){
for(int j=;j<m;j++){
if(vis[str[i][j]-'A']){
for(int k=;k<;k++){
x=i,y=j;//记录下最初的位置,从Trie树根开始向下搜索
dfs(trie[].next[str[i][j]-'A'],i,j,k);
}
}
}
}
for(int i=;i<=w;i++)
printf("%d %d %c\n",out[i][],out[i][],out[i][]+'A');
return ;
}

解法二:AC自动机

参考链接:哔哩哔哩算法讲堂

#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
char str[][],word[];
int n,m,w;
int dir[][]={-,,-,,,,,,,,,-,,-,-,-};//顺时针
char ch[]="ABCDEFGH";
int pos[][];
struct TrieNode{
int id;//记录第几个字符串
TrieNode *next[],*fail;
TrieNode(){
id=,fail=;
memset(next,,sizeof(next));
}
}*root; void InsertNode(char *s,int id)
{
int len=strlen(s)-;
TrieNode *p=root;
while(len>=){//这里将s数组倒着插入字典树,方便匹配时记录匹配的终点即原串的起始点
if(!p->next[s[len]-'A'])
p->next[s[len]-'A']=new TrieNode;
p=p->next[s[len--]-'A'];
}
p->id=id;//id记录单词编号
}
void Build_AC()
{
TrieNode *p,*next;
queue<TrieNode* > que;
que.push(root);
while (!que.empty()){
p=que.front();
que.pop();
for(int i=;i<;i++){
if(p->next[i]){
if(p==root) p->next[i]->fail=root;
else{
TrieNode *temp=p->fail;
while(temp){
if(temp->next[i]){//temp始终代表next[i]的爸爸,有next[i]这个儿子
p->next[i]->fail=temp->next[i];
break;//寻找最长后缀
}
temp=temp->fail;
}
if(!temp) p->next[i]->fail=root;
}
que.push(p->next[i]);
}
}
}
}
void Query(int x,int y,int d,int di)
{
TrieNode *p=root,*next;
while(x>=&&y>=&&x<n&&y<m){
while(p&&!p->next[str[x][y]-'A']) p=p->fail;
if(!p) p=root;
else p=p->next[str[x][y]-'A'];
next=p;
while(next!=root){
if(next->id){//记录原串被匹配的起始点
int k=next->id;
if(pos[k][]>x||(pos[k][]==x&&pos[k][]>y)){
pos[k][]=x;
pos[k][]=y;
pos[k][]=di;//记录单词整体朝向
}
}
next=next->fail;
}
x+=dir[d][];
y+=dir[d][];
}
}
void Free(TrieNode *p)
{
for(int i=;i<;i++){
if(p->next[i])
Free(p->next[i]);
}
delete p;
} int main(){
scanf("%d%d%d",&n,&m,&w);
root=new TrieNode;
for(int i=;i<n;i++)
scanf("%s",str[i]);
for(int i=;i<=w;i++){
scanf("%s",&word);
InsertNode(word,i);
pos[i][]=pos[i][]=inf;
}
Build_AC();
for(int i=;i<m;i++){
Query(,i,,),Query(n-,i,,);
Query(,i,,),Query(n-,i,,);
Query(,i,,),Query(n-,i,,);
}//从矩阵上下左右四条边枚举8个方向
for(int i=;i<n;i++){
Query(i,,,),Query(i,m-,,);
Query(i,,,),Query(i,m-,,);
Query(i,,,),Query(i,m-,,);
}
for(int i=;i<=w;i++)
printf("%d %d %c\n",pos[i][],pos[i][],ch[pos[i][]]);
Free(root);
}

后缀数组倍增解法过一段时间补上

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

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

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

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

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

  3. POJ 1204 Word Puzzles | AC 自动鸡

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

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

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

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

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

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

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

  7. POJ 1204 Word Puzzles(AC自动机)

    这题的数据卡在,如下: 5 5 3 ABCDE FGHIJ KLMNO PQRST UVWXY PQR RS RST puzzle中间的行中可以包含要查询的多个单词.这个问题很好解决,SearchDf ...

  8. poj 1204 Word Puzzles(字典树)

    题目链接:http://poj.org/problem?id=1204 思路分析:由于题目数据较弱,使用暴力搜索:对于所有查找的单词建立一棵字典树,在图中的每个坐标,往8个方向搜索查找即可: 需要注意 ...

  9. 【POJ】1204 Word Puzzles

    这道题目各种wa.首先是错了一个坐标,居然没测出来.然后是剪枝错误.搜索pen时就返回,可能还存在串pen*. #include <cstdio> #include <cstring ...

随机推荐

  1. ORACLE之常用FAQ V1.0

    [B]第一部分.SQL&PL/SQL[/B][Q]怎么样查询特殊字符,如通配符%与_[A]select * from table where name like 'A\_%' escape ' ...

  2. 指针*pbuffer和getchar 读取字符串

    在C语言入门教材里看到这一段代码,没看懂是什么意思.char buffer[10];char *pbuffer = buffer;while( (*pbuffer++ = getchar() )!= ...

  3. CPictureEx类

    CPictueEx类不仅可以显示GIF(包括GIF动画),还可以显示JPEG.BMP.WMF.ICO.CUR等. 参考:https://www.codeproject.com/Articles/142 ...

  4. Text Particle Systems

    一.简介 在一些企业广告或者网站需要一些动态文字特效的时候,往往有下面这几种选择: 1.Flash制作的文字特效 2.制作一个动态的GIF 3.Javascript+dom+css 4.SVG 二.j ...

  5. pushViewController自定义动画http://blog.csdn.net/ralbatr/article/details/22039233

     本文转载至  http://blog.csdn.net/ralbatr/article/details/22039233 实现的主要代码如下: CATransition *transition =  ...

  6. My97DatePicker设置,包括隐藏 清空,设置最大日期等 转载

    My97DatePicker是一款非常灵活好用的日期控件.使用非常简单. 1.下载My97DatePicker组件包 2.在页面中引入该组件js文件:     <script type=&quo ...

  7. 【BZOJ2827】千山鸟飞绝 hash+堆+SBT

    [BZOJ2827]千山鸟飞绝 Description 话说有一天doyouloveme和vfleaking到山里玩.谁知doyouloveme刚刚进山,所有的鸟儿竟被他的神犇气场给惊得全部飞走了.v ...

  8. 浏览器出现“ net::ERR_BLOCKED_BY_CLIENT”错误的解决方法

    转载自:http://www.dbmng.com/art-2136.html Failed to load resource: net::ERR_BLOCKED_BY_CLIENT错误报告 错误原因: ...

  9. HDFS编程

    HDFS编程主要API Hadoop类 功能 org.apache.hadoop.fs.FileSystem 一个通用文件系统的抽象基类,可以被分布式文件系统继承.所有的可能使用Hadoop文件系统的 ...

  10. QBC检索和本地SQL检索

    细说QBC:QBC(Query By Criteria) 查询:这种方式比较面向对象方式,因为是面向对象,所以查询时参数名就是所查询的类的属性名并不是数据库的表的列名重点是有三个描述条件的对象:Res ...