[poj1204][caioj1465][AC自动机]地图匹配
来源:互联网 发布:怎么查看手机端口号 编辑:程序博客网 时间:2024/06/03 22:48
题意
给出有一个L*C的字符地图,地图的行与列都从0开始编号
然后给出一些字符串,求出这些字符串在字符地图上第一次出现的坐标
输出字符串第一个字母的坐标和字符串的方向
字符串的方向是指字符串的走向
A表示正北,B表示东北,C表示正东,D表示东南,E表示正南,F表示西南,G表示正西,H表示西北
且保证字符串的方向是固定的
输入格式
第一行输入L,C,W(0 小于 L,C,W<=1000)
L表示行数,C表示列数,W表示字符串的数量
然后输入L*C的字符矩阵
最后输入W行字符串
输出格式
输出W行,每行对应第i个字符串第一个字母的坐标和字符串的方向
样例输入
20 20 10
QWSPILAATIRAGRAMYKEI
AGTRCLQAXLPOIJLFVBUQ
TQTKAZXVMRWALEMAPKCW
LIEACNKAZXKPOTPIZCEO
FGKLSTCBTROPICALBLBC
JEWHJEEWSMLPOEKORORA
LUPQWRNJOAAGJKMUSJAE
KRQEIOLOAOQPRTVILCBZ
QOPUCAJSPPOUTMTSLPSF
LPOUYTRFGMMLKIUISXSW
WAHCPOIYTGAKLMNAHBVA
EIAKHPLBGSMCLOGNGJML
LDTIKENVCSWQAZUAOEAL
HOPLPGEJKMNUTIIORMNC
LOIUFTGSQACAXMOPBEIO
QOASDHOPEPNBUYUYOBXB
IONIAELOJHSWASMOUTRK
HPOIYTJPLNAQWDRIBITG
LPOINUYMRTEMPTMLMNBO
PAFCOPLHAVAIANALBPFS
MARGARITA
ALEMA
BARBECUE
TROPICAL
SUPREMA
LOUISIANA
CHEESEHAM
EUROPA
HAVAIANA
CAMPONESA
样例输出
0 15 G
2 11 C
7 18 A
4 8 C
16 13 B
4 15 E
10 3 D
5 1 E
19 7 C
11 11 H
题解
ac自动机好题。。MLE炸了我好久。。
首先对单词建自动机,一定要反着来建!!
为什么??顺着跑你怎么记录起始点?八个方向一个个退回去?
所以说反着建啊。搜到s>0了也就到头了,直接记录x,y
反着建了然后暴力搜索,枚举结尾枚举方向扔进自动机
就这样切。。切记不要对图建自动机。。对角线长度建还不炸?
#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue>using namespace std;const int dx[8]={-1,-1,0,1,1,1,0,-1};const int dy[8]={0,1,1,1,0,-1,-1,-1};struct trnode{ int s,fail,c[27]; bool vis; trnode(){s=fail=0;vis=false;memset(c,-1,sizeof(c));}}tr[500010];int tot,root;char s[1005];struct node{ int x,y,w;}a[1005];void clean(int x){ tr[x].s=tr[x].fail=0;tr[x].vis=false; for(int i=1;i<=26;i++)tr[x].c[i]=-1;}void add(int root,int p){ int len=strlen(s),x=root; for(int i=len-1;i>=0;i--) { int y=s[i]-'A'+1; if(tr[x].c[y]==-1) { tr[x].c[y]=++tot; clean(tot); } x=tr[x].c[y]; } tr[x].s=p;}queue<int>q;void build_fail(){ q.push(0); while(!q.empty()) { int x=q.front(); q.pop(); for(int i=1;i<=26;i++) { int son=tr[x].c[i]; if(son==-1)continue; if(x==0)tr[son].fail=0; else { int j=tr[x].fail; while(j && tr[j].c[i]==-1)j=tr[j].fail; tr[son].fail=max(tr[j].c[i],0); } q.push(son); } }}int n,m,member;char map[1001][1001];inline bool check(int x,int y){ if(x>=0 && x<n && y>=0 && y<m)return true; return false;}void Find(int x,int y,int w){ int m=0; while(check(x,y)==true) { int j=map[x][y]-'A'+1; while(m!=0 && tr[m].c[j]==-1)m=tr[m].fail; if(tr[m].c[j]!=-1)m=tr[m].c[j]; for(int k=m;k!=0 && tr[k].vis==false;k=tr[k].fail) { if(tr[k].s>0) { int l=tr[k].s; a[l].x=x;a[l].y=y; a[l].w=(w+4)%8; } tr[k].vis=true; } x+=dx[w];y+=dy[w]; }}int main(){ scanf("%d%d%d",&n,&m,&member); clean(0);tot=0; for(int i=0;i<n;i++)scanf("%s",map[i]); for(int i=1;i<=member;i++) { scanf("%s",s); add(0,i); } build_fail(); for(int i=0;i<n;i++) Find(i,0,1),Find(i,0,2),Find(i,0,3),Find(i,m-1,5),Find(i,m-1,6),Find(i,m-1,7); for(int j=0;j<m;j++) Find(0,j,3),Find(0,j,4),Find(0,j,5),Find(n-1,j,0),Find(n-1,j,1),Find(n-1,j,7); for(int i=1;i<=member;i++)printf("%d %d %c\n",a[i].x,a[i].y,a[i].w+'A'); return 0;}
- [poj1204][caioj1465][AC自动机]地图匹配
- poj1204Word Puzzles,caioj1465地图匹配(AC自动机+搜索)
- poj1204(AC自动机)
- poj1204之AC自动机
- POJ1204 AC自动机
- 【AC自动机】地图匹配
- POJ1204 Word Puzzles AC自动机
- POJ1204--Word Puzzles--AC自动机
- 【POJ1204】Word Puzzles-AC自动机
- 【POJ1204】Word Puzzles——AC自动机
- 字符串匹配-AC自动机
- AC自动机通配符匹配
- AC自动机通配符匹配
- AC自动机匹配
- 多串匹配-AC自动机
- 多串匹配 AC自动机
- AC自动机(多模串匹配)
- 【AC自动机+DP】匹配(match)
- 图像超分辨率技术
- 指针建树
- 1、思考数据结构中逻辑结构、物理结构、操作运算三个方面的内容
- Crontab 设置定时抽取任务
- uva 10791
- [poj1204][caioj1465][AC自动机]地图匹配
- 简单实现日夜间模式切换
- [LeetCode-Algorithms-13] "Roman to Integer" (2017.9.22-WEEK3)
- GPRS模块与STM32的数据传输
- 51nod 1419 最小公倍数挑战
- Selenium遇到的问题6 利用fiddler抓包工具,Host总是显示Tunnel to
- 2. Add Two Numbers。
- 训练集---训练赛11
- Akka的设计理念