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