poj1204(AC自動機,模板)
阿新 • • 發佈:2018-12-12
題意:給個L*C的字串矩陣,W個詢問,對每個詢問輸出這個串第一次出現的位置及方向,共有8個方向,用A~H表示
思路:其實就是普通的AC自動機,但由於有八個方向,所以要把各種方向的可能性都給試一遍。注意,由於要記錄開始字串,所以在構造tire樹的時候就應該把那些字串倒過來構造,切記。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; char s[1005][1005]; char tp[1005]; int ans[1005][3],l,c,w; struct node { node *next[26],*fail; int fg; node() { fail=NULL; for(int i=0;i<26;i++) next[i]=NULL; fg=0; } }*q[500000],*root; int dir[8][3]={{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}}; void build_tire(node *p,int id) { int t=strlen(tp); for(int i=t-1;i>=0;i--) { if(p->next[tp[i]-'A']==NULL) { p->next[tp[i]-'A']=new node(); } p=p->next[tp[i]-'A']; } p->fg=id; } void make_ac(node *p) { node *temp,*temp1; int head,tail; head=tail=0; q[tail++]=p; while(head!=tail) { temp=q[--tail]; for(int i=0;i<26;i++) { if(temp->next[i]!=NULL) { if(temp==root) temp->next[i]->fail=root; else { temp1=temp->fail; while(temp1!=NULL) { if(temp1->next[i]!=NULL) { temp->next[i]->fail=temp1->next[i]; break; } temp1=temp1->fail; } if(temp1==NULL) temp->next[i]->fail=root; } q[tail++]=temp->next[i]; } } } } void query(int x,int y,int id,int id1) { node *p=root,*temp; while(x>=0&&y>=0&&x<l&&y<c) { int t=s[x][y]-'A'; while(p->next[t]==NULL&&p!=root) p=p->fail; p=p->next[t]; if(p==NULL) p=root; temp=p; while(temp!=root) { if(temp->fg) { ans[temp->fg][0]=x; ans[temp->fg][1]=y; ans[temp->fg][2]=id1; } temp=temp->fail; } x+=dir[id][1]; y+=dir[id][0]; } } void del(node *p) { if(p==NULL)return ; for(int i=0;i<26;i++)del(p->next[i]); delete p; } int main() { //freopen("t.txt","r",stdin); while(scanf("%d%d%d",&l,&c,&w)!=EOF) { memset(ans,-1,sizeof(ans)); root= new node(); for(int i=0;i<l;i++) {scanf("%s",s[i]);} for(int i=1;i<=w;i++) { scanf("%s",tp); build_tire(root,i); } make_ac(root); for(int i=0;i<l;i++) { query(i,0,1,5); query(i,0,2,6); query(i,0,3,7); query(i,c-1,7,3); query(i,c-1,6,2); query(i,c-1,5,1); } for(int j=0;j<c;j++) { query(l-1,j,1,5); query(l-1,j,0,4); query(l-1,j,7,3); query(0,j,3,7); query(0,j,4,0); query(0,j,5,1); } for(int i=1;i<=w;i++) { char t=ans[i][2]+'A'; printf("%d %d %c\n",ans[i][0],ans[i][1],t); } del(root); } return 0; }