poj1204——Word Puzzles

ac自动机应用。遍历图八次,直到w个单词都被找到。

#include<iostream> #include<string> #include<cstdio> using namespace std; int dir[][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}}; class word { public: char ch[1001]; int x,y,len; char dirr; bool vis; word() { vis=false; } }; word str[1005]; class node { public: node *fail; node *next[28]; int cnt; node() { cnt=-1; memset(next,NULL,sizeof(next)); } }; node * que[1000008]; node *tire; char g[1005][1005]; int n,m,w; void insert(int index) { node *p=tire; int i,len=str[index].len ; for(i=0;i<len;i++) { int k=str[index].ch [i]-'A'; if(p->next [k]==NULL) p->next [k]= new node(); p=p->next [k]; } p->cnt =index; } void bfs() { int front=0,rear=0; int i; tire->fail =NULL; rear++; que[rear]=tire; while(front!=rear) { front++; node *temp=que[front]; node *p; for(i=0;i<26;i++) if(temp->next [i]!=NULL) { p=temp->fail ; while(p!=NULL) { if(p->next [i]!=NULL) { temp->next [i]->fail =p->next [i]; break; } p=p->fail ; } if(p==NULL) temp->next [i]->fail =tire; rear++; que[rear]=temp->next [i]; } } } bool isok(int x,int y) { if(x>=0&&x<n&&y>=0&&y<m)return true; return false; } void ac(int stx,int sty,int dirr) { int tempx=stx,tempy=sty; node *temp=tire; while(1) { if(isok(tempx,tempy)) { int k=g[tempx][tempy]-'A'; while(temp->next [k]==NULL&&temp!=tire) temp=temp->fail ; temp=temp->next [k]; if(temp==NULL) temp=tire; node *p=temp; while(p!=tire&&p->cnt !=-1) { str[p->cnt ].vis =true; str[p->cnt ].x =tempx; str[p->cnt ].y =tempy; str[p->cnt ].dirr =dirr; w--; p->cnt =-1; p=p->fail ; } } else return ; tempx=tempx+dir[dirr][0]; tempy=tempy+dir[dirr][1]; } } void solve() { int i,j; int num=w; for(i=0;i<m;i++) { ac(0,i,4); ac(0,i,3); ac(0,i,5); ac(n-1,i,0); ac(n-1,i,1); ac(n-1,i,7); } for(i=0;i<n;i++) { ac(i,0,2); ac(i,0,1); ac(i,0,3); ac(i,m-1,6); ac(i,m-1,5); ac(i,m-1,7); } for(i=0;i<num;i++) { int k=str[i].len -1; if(str[i].dirr ==0||str[i].dirr ==1||str[i].dirr ==7) str[i].x +=k; if(str[i].dirr >=3&&str[i].dirr <=5) str[i].x -=k; if(str[i].dirr >=1&&str[i].dirr <=3) str[i].y -=k; if(str[i].dirr >=5&&str[i].dirr <=7) str[i].y +=k; printf("%d %d %c\n",str[i].x ,str[i].y ,str[i].dirr +'A'); } } int main() { int i,j; tire= new node; for(i=0;i<26;i++) tire->next [i]=NULL; scanf("%d%d%d",&n,&m,&w); getchar(); for(i=0;i<n;i++) { scanf("%s",g[i]); } for(i=0;i<w;i++) { scanf("%s",str[i].ch ); str[i].len =strlen(str[i].ch ); insert(i); } bfs(); solve(); return 0; }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值