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
【AC自动机】地图匹配
最新推荐文章于 2024-07-28 05:36:00 发布