UVA1127 Word Puzzles

我们对模式串建立AC自动机,然后就比较板子了,只需要把\(8\)个方向都跑一遍匹配就可以了。

对于单个测试数据,建自动机复杂度是\(O(\sum|s|\ |\Sigma|)\),总时间复杂度是\(O(\sum|s|\ |\Sigma|+8nm)\)。

注意输入是大写字母。

点击查看代码
#include<bits/stdc++.h>
#define K 1010//模式串个数 & 矩阵长宽
#define N 1000010//节点个数(模式串总长)
#define C 26//字符集大小
using namespace std;
int tt,n,m,k;
int cnt,tr[N][C],fail[N],en[N],len[N];
int q[N],head,tail;
int ansx[K],ansy[K],ansd[K];
int dx[8]{-1,-1,0,1,1,1,0,-1},dy[8]{0,1,1,1,0,-1,-1,-1};
string s[K],t;
void clear(int x){
memset(tr[x],0,sizeof tr[x]);
fail[x]=en[x]=len[x]=0;
}
void ins(string s,int num){
int p=0;
for(char i:s){
int c=i-'A';
if(!tr[p][c]) tr[p][c]=++cnt,clear(cnt);
p=tr[p][c];
}
en[p]=num,len[p]=s.size();
}
void get_fail(){
head=0,tail=-1;
for(int i=0;i<26;i++) if(tr[0][i]) q[++tail]=tr[0][i];
while(head<=tail){
int u=q[head++];
for(int i=0;i<26;i++){
if(tr[u][i]) fail[tr[u][i]]=tr[fail[u]][i],q[++tail]=tr[u][i];
else tr[u][i]=tr[fail[u]][i];
}
}
}
void query(int x,int y,int d){
int p=0;
while(x<n&&y<m&&x>=0&&y>=0){
p=tr[p][s[x][y]-'A'];
int xx=x-dx[d]*(len[p]-1),yy=y-dy[d]*(len[p]-1);//开始位置
if(en[p]&&(xx<ansx[en[p]]||(xx==ansx[en[p]]&&yy<ansy[en[p]])))
ansx[en[p]]=xx,ansy[en[p]]=yy,ansd[en[p]]=d;
x+=dx[d],y+=dy[d];
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin>>tt;
while(tt--){
memset(ansx,127,sizeof ansx);
memset(ansy,127,sizeof ansy);
clear(0);
cin>>n>>m>>k;
for(int i=0;i<n;i++) cin>>s[i];
for(int i=1;i<=k;i++){
cin>>t;
ins(t,i);
}
get_fail();
for(int i=0;i<n;i++) for(int j=0;j<8;j++) query(i,0,j),query(i,m-1,j);
for(int i=0;i<n;i++) for(int j=0;j<8;j++) query(0,i,j),query(n-1,i,j);
for(int i=1;i<=k;i++)
cout<<ansx[i]<<" "<<ansy[i]<<" "<<char(ansd[i]+'A')<<"\n";
cout<<"\n";
}
return 0;
}

上面的写法是每匹配成功,就计算得到字符串的开始位置。

还有一种写法,就是反向建Trie,把模式串全部翻转再扔进去。这样匹配成功的位置直接就是字符串的开始位置了,效率会高不少(370ms => 210ms)。需要注意这样写的话,匹配成功时的方向和实际方向是相反的,需要反向一下。

点击查看代码
#include<bits/stdc++.h>
#define K 1010//模式串个数 & 矩阵长宽
#define N 1000010//节点个数(模式串总长)
#define C 26//字符集大小
using namespace std;
int tt,n,m,k;
int cnt,tr[N][C],fail[N],en[N];
int q[N],head,tail;
int ansx[K],ansy[K],ansd[K];
int dx[8]{-1,-1,0,1,1,1,0,-1},dy[8]{0,1,1,1,0,-1,-1,-1};
string s[K],t;
void clear(int x){
memset(tr[x],0,sizeof tr[x]);
fail[x]=en[x]=0;
}
void ins(string s,int num){
int p=0,n=s.size();
for(int i=n-1;i>=0;i--){
int c=s[i]-'A';
if(!tr[p][c]) tr[p][c]=++cnt,clear(cnt);
p=tr[p][c];
}
en[p]=num;
}
void get_fail(){
head=0,tail=-1;
for(int i=0;i<26;i++) if(tr[0][i]) q[++tail]=tr[0][i];
while(head<=tail){
int u=q[head++];
for(int i=0;i<26;i++){
if(tr[u][i]) fail[tr[u][i]]=tr[fail[u]][i],q[++tail]=tr[u][i];
else tr[u][i]=tr[fail[u]][i];
}
}
}
void query(int x,int y,int d){
int p=0;
while(x<n&&y<m&&x>=0&&y>=0){
p=tr[p][s[x][y]-'A'];
if(en[p]&&(x<ansx[en[p]]||(x==ansx[en[p]]&&y<ansy[en[p]])))
ansx[en[p]]=x,ansy[en[p]]=y,ansd[en[p]]=(d+4)%8;//+4是因为Trie是倒着建的
x+=dx[d],y+=dy[d];
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin>>tt;
while(tt--){
memset(ansx,127,sizeof ansx);
memset(ansy,127,sizeof ansy);
clear(0);
cin>>n>>m>>k;
for(int i=0;i<n;i++) cin>>s[i];
for(int i=1;i<=k;i++){
cin>>t;
ins(t,i);
}
get_fail();
for(int i=0;i<n;i++) for(int j=0;j<8;j++) query(i,0,j),query(i,m-1,j);
for(int i=0;i<n;i++) for(int j=0;j<8;j++) query(0,i,j),query(n-1,i,j);
for(int i=1;i<=k;i++)
cout<<ansx[i]<<" "<<ansy[i]<<" "<<char(ansd[i]+'A')<<"\n";
cout<<"\n";
}
return 0;
}

[题解]UVA1127 Word Puzzles的更多相关文章

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

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

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

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

  3. poj1204 Word Puzzles

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

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

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

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

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

  6. POJ1204:Word Puzzles——题解

    http://poj.org/problem?id=1204 题目大意:给一个字母表,求一些字符串的开端第一次出现的位置和字符串的方向(字符串可以按照八个方向放在字母表中可匹配的位置) ——————— ...

  7. Word Puzzles

    poj1204:http://poj.org/problem?id=1204 题意:给你n*m的字符串矩阵,然后p个查询,每个查询会给出一个字符串,然后问你在矩阵中能否通过8个方向搜索到这个字符串,输 ...

  8. PKU 1204 Word Puzzles(AC自动机)

    题目大意:原题链接 给定一个字符串矩阵和待查找的单词,可以朝8个不同的方向查找,输出待查找单词第一个字母在矩阵中出现的位置和该单词被查到的方向. A~H代表8个不同的方向,A代表正北方向,其他依次以4 ...

  9. POJ 1204 Word Puzzles | AC 自动鸡

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

  10. POJ1204 Word Puzzles(AC自动机)

    给一个L*C字符矩阵和W个字符串,问那些字符串出现在矩阵的位置,横竖斜八个向. 就是个多模式匹配的问题,直接AC自动机搞了,枚举字符矩阵八个方向的所有字符串构成主串,然后在W个模式串构造的AC自动机上 ...

随机推荐

  1. ubuntu22.04使用libmysqlclient-dev,在包含mysql.h时会出现‘net_async_status’未声明

    //mysql Ver 8.0.41-0ubuntu0.22.04.1 for Linux on x86_64 ((Ubuntu)) //库文件是libmysqlclient-dev //在使用 g+ ...

  2. 敏捷史话(十):我牺牲了滑雪时间,参加了一场软件革命——Jon Kern

    "在镜头定格的一刹那,所有美好都和你不期而遇",这是 Jon Kern 对生活的表达.为了更好地记录生活,他在一家名为 flickr 的网站上创建了一个属于自己的照片博客,在这个博 ...

  3. controller的简单介绍

    介绍 Kubernetes控制器是一个主动调谐的过程,它会watch一些对象的期望状态,也会watch实际的状态,然后控制器会发送一些指令尝试让对象的当前状态往期望状态迁移. 控制器最简单的实现就是一 ...

  4. Go mod/work/get ... Golang 提供的项目管理工具该怎么用?

    自 Go 1.11 版本引入 模块(modules) 的概念以来,Go 语言的项目管理和依赖管理方式发生了根本性的变革.这一变化旨在解决早期 GOPATH 模式带来的种种不便,让项目结构更加清晰,依赖 ...

  5. 数栈云MSP运维服务案例:某客户生产服务器CPU异常抖动

    一.问题背景 某日袋鼠云运维小哥进行例行运维巡检,通过监控视图发现客户应用服务器cpu使用率突然呈上升趋势.通过专属服务群第一时间与业务方联系,与业务方确认是否有正在执行的定时任务,或者大范围拉取账单 ...

  6. DRF之排序类源码分析

    DRF之排序类源码分析 [一]排序类介绍 在Django REST framework (DRF)中,排序类用于处理API端点的排序操作,允许客户端请求按特定字段对数据进行升序或降序排序. 排序类是一 ...

  7. CMD 命令启动管理员模式代码

    ::==========================================:: 获取管理员权限set _Args=%*if "%~1" NEQ "" ...

  8. FFmpeg开发笔记(七十三)Windows给FFmpeg集成MPEG-5视频编解码器

    ​MPEG-5是新一代的国际音视频编解码标准,像我们熟悉的MP3.MP4等音视频格式就来自于MPEG系列.MP3格式的说明介绍参见<FFmpeg开发实战:从零基础到短视频上线>一书的&qu ...

  9. off 表面三角网格翻转问题解决

    简介 参考链接 https://gamedev.stackexchange.com/questions/26974/repairing-back-facing-triangles-without-us ...

  10. java 中的equals hashCode

    简介 hashCode 与 equals 应该有等同性,如果A equals B 那么 A 和 B 的hashCode 应该一样 还有toString方法可以在后期调试的过程中起到很好的作用 code ...