AC automaton Exercises: map matching

AC automaton board before, to learn and if you forget to look at

1465: AC automatic machine] [map matching

poj1204

Time limit: 1 Sec   Memory Limit: 256 MB
submit: 78   Resolution: 46
[ submit ] [ state ] [ Discussion Board ] [proposition man: ADMIN ]

Title Description

[Title] Italy
L * C is given a character map, rows and columns are numbered from 0
and then give some string, these strings to obtain the coordinates of the map's first appearance in the character of
the output string first letter character string direction and the coordinates of
the direction of a character string refers to a character string
a represents north, B represents the northeast, C denotes east, D denotes the southeast, E denotes south, F represents southwest, G represents a due west, H It represents the northwest
and to ensure that the direction of the string is fixed

[Input format
of the first input line L, C, W (0 <L, C, W <= 1000)
L represents the number of rows, C represents the number of column, W represents the number string
and character input matrix L * C
final W input line string
[] output format
output W row, the direction of the first letter corresponding to the i-th row for each coordinate string and character string
[] sample input
20 is 20 is 10
QWSPILAATIRAGRAMYKEI
AGTRCLQAXLPOIJLFVBUQ
TQTKAZXVMRWALEMAPKCW
LIEACNKAZXKPOTPIZCEO
FGKLSTCBTROPICALBLBC
JEWHJEEWSMLPOEKORORA
LUPQWRNJOAAGJKMUSJAE
KRQEIOLOAOQPRTVILCBZ
QOPUCAJSPPOUTMTSLPSF
LPOUYTRFGMMLKIUISXSW
WAHCPOIYTGAKLMNAHBVA
EIAKHPLBGSMCLOGNGJML
LDTIKENVCSWQAZUAOEAL
HOPLPGEJKMNUTIIORMNC
LOIUFTGSQACAXMOPBEIO
QOASDHOPEPNBUYUYOBXB
IONIAELOJHSWASMOUTRK
HPOIYTJPLNAQWDRIBITG
LPOINUYMRTEMPTMLMNBO
PAFCOPLHAVAIANALBPFS
MARGARITA
GERMAN
BARBECUE
TROPICAL
SUPREME
LOUISIANA
CHEESEHAM
EUROPE
HAWAIIAN
PEASANT
【】样例输出
0 15 G
2 11 C
7 18
4 8 C
16 B 13
4 15 E
10 3 D
5 E 1
19 7 C
11 H 11

 First of all the AC board and almost automatic machine is the same, but this turned into a two-dimensional, and we now look at some small details to pay attention to this question of

  • First, we have this question because the letter is a matrix which has appeared many times, but we have to find the letters first appeared to meet the conditions, so we know more than we add a variable to hold the current of the letter has not been searched and then because of the increase direction, which means that we should want to pre-position each position of the boundary

                                                                           

  • Then that is our contribution to build backwards, why? Because this way, we can directly in the search for the end of time, to find the beginning, and then record the location

The main is that these two details, see the rest of the board is almost the same as AC automatic machine code

Code implementation

(注释版,我觉得不看注释版都可以理解的代码就尽量不看吧

  1 /*有一个要注意的,就是横纵左边的起始位置为0,所以我们在计算字符串的时候一定要是开头为0*/
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<iostream>
  8 using namespace std;
  9 const int dx[8]={-1,-1,0,1,1, 1, 0,-1};
 10 const int dy[8]={ 0, 1,1,1,0,-1,-1,-1};
 11 /*正西 西南 正南 东南 正东 东北 正北 西北*/
 12 struct trie/*字典树*/
 13 {
 14     int s,cnt[30],fail,b;
 15     /*fail就是失败指针,cnt就是孩子,s记录开头所对应的数据,b是记录他有没有被记录过,这里就没有必要初始化了,一百万初始化还是不太好*/ 
 16 }tr[1000010];
 17 struct node/*保存答案的结构体*/
 18 {
 19     int x,y,c;/*x,y表示左边,c表示方向*/
 20 }a[1010];
 21 char map[1010][1010],s[1010];
 22 int tot,list[500010],n,m,t;
 23 void clean(int x)/*虽然没有多组数据,但是也要清空,因为我们在建树的时候清空子树可以节省时间*/
 24 {
 25     tr[x].b=tr[x].s=tr[x].fail=0;
 26     memset(tr[x].cnt,-1,sizeof(tr[x].cnt));
 27 }
 28 void build_tree(int id)/*建树的板子*/
 29 {
 30     int x=0; int len=strlen(s);
 31     for(int i=len-1;i>=0;i--)/*倒着建树,方便匹配时记录匹配的终点即为原串的起始点*/
 32     {
 33         int y=s[i]-'A';/*没有+1是因为我们从0开始*/
 34         if(tr[x].cnt[y]==-1)
 35         {
 36             tr[x].cnt[y]=++tot;
 37             clean(tot);
 38         }
 39         x=tr[x].cnt[y];
 40     }
 41     tr[x].s=id;/*记录这个单词开头的编号,因为我们是倒着建树的
 42     也就是说我们的tot对应的单词是开头的,把他为第几组数据记录下来*/
 43 }
 44 void bfs()/*构造失败指针的板子*/
 45 {
 46     list[1]=0; int head=1,tail=1;
 47     while(head<=tail)
 48     {
 49         int x=list[head];
 50         for(int i=0;i<26;i++)
 51         {
 52             int son=tr[x].cnt[i];
 53             if(son==-1) continue;
 54             if(x==0) tr[son].fail=0;
 55             else
 56             {
 57                 int j=tr[x].fail;
 58                 while(j!=0 && tr[j].cnt[i]==-1) j=tr[j].fail;
 59                 tr[son].fail=max(tr[j].cnt[i],0);
 60             }
 61             list[++tail]=son;
 62         }
 63         head++;
 64     }
 65 }
 66 bool check(int x,int y)/*判断一下这个左边能不能进入搜索的范围*/ 
 67 {
 68     if(x<0 || y<0 || x>=n || y>=m) return 0;
 69     return 1;
 70 }
 71 void query(int x,int y,int c)
 72 {
 73     int w=0;
 74     while(check(x,y))/*可以进入搜索范围*/
 75     {
 76         int j=map[x][y]-'A';/*把他转化为个数*/
 77         while(w!=0 && tr[w].cnt[j]==-1) w=tr[w].fail;
 78         if(tr[w].cnt[j]!=-1) w=tr[w].cnt[j];/*同样的就是找失败指针来记录*/
 79         for(int k=w; k!=0 && !tr[k].b;k=tr[k].fail)
 80         /*从我们当前当的位置开始,保证他不是根节点,并且没有记录过,然后找他的失败指针*/
 81         {
 82             if(tr[k].s)/*找到原串被匹配的起始点*/
 83             {
 84                 int l=tr[k].s;
 85                 a[l].x=x;
 86                 a[l].y=y;/*记录下来横纵坐标*/
 87                 a[l].c=(c+4)%8;/*同种类型的有四种,全部类型有八种*/
 88             }
 89             tr[k].b=1;/*更新为记录过*/   
 90         }
 91         x+=dx[c],y+=dy[c];/*按照这个方向往下寻找*/
 92     }
 93 }
 94 int main()
 95 {
 96     scanf("%d%d%d",&n,&m,&t);
 97     clean(0); tot=0;
 98     memset(a,-1,sizeof(a));/*初始化*/
 99     for(int i=0;i<n;i++) scanf("%s",map[i]);
100     /*直接把一行字符输进去,一维的我们是直接map+1,和现在一样*/
101     for(int i=1;i<=t;i++)
102     {
103         scanf("%s",s);
104         build_tree(i);/*建树*/
105     }
106     bfs();/*构造失败指针*/
107     /*总共有八个方向,0~7,从最上面开始按照顺时针一周*/
108     for(int i=0;i<n;i++)
109     {
110         query(i,0,1); query(i,0,2); query(i,0,3);/*右边*/
111         query(i,m-1,5); query(i,m-1,6); query(i,m-1,7);/*左边*/
112     }
113     for(int i=0;i<m;i++)
114     {
115         query(0,i,3); query(0,i,4); query(0,i,5);/*下面*/
116         query(n-1,i,0); query(n-1,i,1); query(n-1,i,7);/*上面*/ 
117     }
118     /*两重循环加一起起始就是把我们矩阵的外围给围起来的,起始就是说把最外面的有可能走的方向都用AC自动机找一遍*/ 
119     for(int i=1;i<=t;i++) printf("%d %d %c\n",a[i].x,a[i].y,a[i].c+'A');
120     return 0;
121 }
Tristan Code 注释版

(非注释版,一个更好锻炼理解代码能力的代码

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<iostream>
  7 using namespace std;
  8 const int dx[8]={-1,-1,0,1,1, 1, 0,-1};
  9 const int dy[8]={ 0, 1,1,1,0,-1,-1,-1};
 10 struct trie
 11 {
 12     int s,cnt[30],fail,b;
 13 }tr[1000010];
 14 struct node
 15 {
 16     int x,y,c;
 17 }a[1010];
 18 char map[1010][1010],s[1010];
 19 int tot,list[500010],n,m,t;
 20 void clean(int x)
 21 {
 22     tr[x].b=tr[x].s=tr[x].fail=0;
 23     memset(tr[x].cnt,-1,sizeof(tr[x].cnt));
 24 }
 25 void build_tree(int id)
 26 {
 27     int x=0; int len=strlen(s);
 28     for(int i=len-1;i>=0;i--)
 29     {
 30         int y=s[i]-'A';
 31         if(tr[x].cnt[y]==-1)
 32         {
 33             tr[x].cnt[y]=++tot;
 34             clean(tot);
 35         }
 36         x=tr[x].cnt[y];
 37     }
 38     tr[x].s=id;
 39 }
 40 void bfs()
 41 {
 42     list[1]=0; int head=1,tail=1;
 43     while(head<=tail)
 44     {
 45         int x=list[head];
 46         for(int i=0;i<26;i++)
 47         {
 48             int son=tr[x].cnt[i];
 49             if(son==-1) continue;
 50             if(x==0) tr[son].fail=0;
 51             else
 52             {
 53                 int j=tr[x].fail;
 54                 while(j!=0 && tr[j].cnt[i]==-1) j=tr[j].fail;
 55                 tr[son].fail=max(tr[j].cnt[i],0);
 56             }
 57             list[++tail]=son;
 58         }
 59         head++;
 60     }
 61 }
 62 bool check(int x,int y)
 63 {
 64     if(x<0 || y<0 || x>=n || y>=m) return 0;
 65     return 1;
 66 }
 67 void query(int x,int y,int c)
 68 {
 69     int w=0;
 70     while(check(x,y))
 71     {
 72         int j=map[x][y]-'A';
 73         while(w!=0 && tr[w].cnt[j]==-1) w=tr[w].fail;
 74         if(tr[w].cnt[j]!=-1) w=tr[w].cnt[j];
 75         for(int k=w; k!=0 && !tr[k].b ;k=tr[k].fail)
 76         {
 77             if(tr[k].s)
 78             {
 79                 int l=tr[k].s;
 80                 a[l].x=x;
 81                 a[l].y=y;
 82                 a[l].c=(c+4)%8;
 83             }
 84             tr[k].b=1;
 85         }
 86         x+=dx[c],y+=dy[c];
 87     }
 88 }
 89 int main()
 90 {
 91     scanf("%d%d%d",&n,&m,&t);
 92     clean(0); tot=0;
 93     memset(a,-1,sizeof(a));
 94     for(int i=0;i<n;i++) scanf("%s",map[i]);
 95     for(int i=1;i<=t;i++)
 96     {
 97         scanf("%s",s);
 98         build_tree(i);
 99     }
100     bfs();
101     for(int i=0;i<n;i++)
102     {
103         query(i,0,1); query(i,0,2); query(i,0,3);
104         query(i,m-1,5); query(i,m-1,6); query(i,m-1,7);
105     }
106     for(int i=0;i<m;i++)
107     {
108         query(0,i,3); query(0,i,4); query(0,i,5);
109         query(n-1,i,0); query(n-1,i,1); query(n-1,i,7);
110     }
111     for(int i=1;i<=t;i++) printf("%d %d %c\n",a[i].x,a[i].y,a[i].c+'A');
112     return 0;
113 }
Tristan Code 非注释版

Guess you like

Origin www.cnblogs.com/Tristanjiang/p/11368265.html