hz2016评测《《点击访问《《增加了内存
caioj《《点击访问
这题其实还是模版题吧,说难不难,说不难还是很难。
我们不能按照暴力的思想,给图for8个方向建树。
这样会超时的。
所以悲伤的我们只好测试可不可以反着建。
最后我们总结出反着建句子的字典树,然后离线找匹配。
例如一个5*5的地图
11111
12221
12321
12221
11111
先在1号的点向八个方向去字符树里面匹配
然后就是2的点,最后3号点,总会匹配到适合的字符串。
所以这题就解出来了。
#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Maxchar 1000000
#define Maxm 1000
#define Maxn 1000
#define Maxs 26
#define mes(x,y) memset(x,y,sizeof(x));
#define mpy(x,y) memcpy(x,y,sizeof(x))
#define INF 2147483647
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 Tire{
int s,fail,c[Maxs+1];
bool v;
void clear(){
s=fail=0;v=false;
mes(c,-1);
}
}tr[Maxm*Maxm+1];
int tot;
char s[Maxn+1];
struct node{
int x,y,w;
}a[Maxn+1];
map<int, map<int,int> >qt;
void add(int root,int p) {
int x=root,len=strlen(s+1);
for(int i=len;i>=1;i--){
int y=s[i]-'A'+1;
if(tr[x].c[y]==-1){
tr[x].c[y]=++tot;
tr[tot].clear();
}
x=tr[x].c[y];
}
tr[x].s=p;
}
queue<int> q;
void build_fail(){
int x,y,son;
q.push(0);
while(q.empty()==false) {
x=q.front();
for(int i=1;i<=26;i++){
son=tr[x].c[i];
if(son==-1)continue;
if(x==0)tr[son].fail=0;
else{
int j=tr[x].fail;
while(j>0&&tr[j].c[i]==-1)j=tr[j].fail;
tr[son].fail=max(tr[j].c[i],0);
}
q.push(son);
}
q.pop();
}
}
int n,m,member;
char maps[Maxm+1][Maxm+1];
inline bool check(int x,int y){
if(x>=1&&x<=n&&y>=1&&y<=m)return true;
return false;
}
void Find(int x,int y,int w){
int m=0;
while(check(x,y)==true){
int j=maps[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].v==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].v=true;
}
x+=dx[w];
y+=dy[w];
}
}
int main(){
scanf("%d%d%d",&n,&m,&member);
tr[0].clear();
tot=0;
for(int i=1;i<=n;i++)scanf("%s",maps[i]+1);
for(int i=1;i<=member;i++){
scanf("%s",s+1);
add(0,i);
}
build_fail();
for(int i=1;i<=n;i++)Find(i,1,1),Find(i,1,2),Find(i,1,3),Find(i,m,5),Find(i,m,6),Find(i,m,7);
for(int j=1;j<=m;j++)Find(1,j,3),Find(1,j,4),Find(1,j,5),Find(n,j,0),Find(n,j,1),Find(n,j,7);
for(int i=1;i<=member;i++)printf("%d %d %c\n",a[i].x-1,a[i].y-1,a[i].w+'A');
return 0;
}
查看原文:http://hz2016.tk/blog/?p=41