【AC自动机】地图匹配

来源:互联网 发布:张玮 high 知乎 编辑:程序博客网 时间:2024/06/04 22:59
hz2016评测《《点击访问《《增加了内存caioj《《点击访问这题其实还是模版题吧,说难不难,说不难还是很难。我们不能按照暴力的思想,给图for8个方向建树。这样会超时的。所以悲伤的我们只好测试可不可以反着建。最后我们总结出反着建句子的字典树,然后离线找匹配。例如一个5*5的地图
1111112221123211222111111
先在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 2147483647using 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
原创粉丝点击