题意:这道题还是蛮有意思的,首先,他给出一个n * m 的表格,里面都是大写字母,然后再给出k个串,问这个k个串在表格的什么位置,输出起始坐标和每个串在表格中的方向,一共8个方向。
思路:一开始就想,对表格的八个方向都建一个AC自动机,然后拿k个串一个一个匹配,但是发现代码复杂度极高,非常不好实现。
那可以从串的角度考虑,我们对这些串建一个TRIE树,那么每次枚举表格的起点,然后从这个起点出发,沿着八个方向搜一遍,看是否有匹配上的前缀,直接记录即可。
但是,需要注意的一点是,每次搜到一个前缀的时候,切记不可直接return .
我们考虑这样的两个串
abcd
abcde
对于串2,要搜到他显然得先搜到串1,所以搜到串1的时候不能return ,否则就搜不到串2了,具体见代码。
#include <set> #include <map> #include <stack> #include <cmath> #include <queue> #include <cstdio> #include <string> #include <vector> #include <iomanip> #include <cstring> #include <iostream> #include <algorithm> #define Max 2505 #define FI first #define SE second #define ll long long #define PI acos(-1.0) #define inf 0x3fffffff #define LL(x) ( x << 1 ) #define bug puts("here") #define PII pair<int,int> #define RR(x) ( x << 1 | 1 ) #define mp(a,b) make_pair(a,b) #define mem(a,b) memset(a,b,sizeof(a)) #define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i ) using namespace std; inline void RD(int &ret) { char c; int flag = 1 ; do { c = getchar(); if(c == '-')flag = -1 ; } while(c < '0' || c > '9') ; ret = c - '0'; while((c=getchar()) >= '0' && c <= '9') ret = ret * 10 + ( c - '0' ); ret *= flag ; } inline void OT(int a) { if(a >= 10)OT(a / 10) ; putchar(a % 10 + '0') ; } inline void RD(double &ret) { char c ; int flag = 1 ; do { c = getchar() ; if(c == '-')flag = -1 ; } while(c < '0' || c > '9') ; ll n1 = c - '0' ; while((c = getchar()) >= '0' && c <= '9') { n1 = n1 * 10 + c - '0' ; } ll n2 = 1 ; while((c = getchar()) >= '0' && c <= '9') { n1 = n1 * 10 + c - '0' ; n2 *= 10 ; } ret = flag * (double)n1 / (double)(n2) ; } /*********************************************/ #define N 1111111 int n , m ; struct TT { int next[26] ; int count ; void init() { mem(next , 0) ; count = 0 ; } } T[N] ; int num = 0 ; char Map[1111][1111] ; void init() { num = 0 ; T[0].init() ; } void insert(char *a ,int id) { int l = strlen(a) ; int now = 0 ; for (int i = 0 ; i < l ; i ++ ) { int k = a[i] - 'A' ; if(T[now].next[k] == 0) { T[now].next[k] = ++ num ; T[num].init() ; } now = T[now].next[k] ; } T[now].count = id ; } int fkk = 0 ; int mx[8] = {-1 , -1 , 0 , 1 , 1 , 1 , 0 , -1} ; int my[8] = { 0 , 1 , 1 , 1 , 0 , -1 ,-1 , -1} ; struct ANS { int s , e ; char fk ; } ans[N] ; int s , e ; int inmap(int x ,int y) { if(x >= 0 && x < n && y >= 0 && y < m)return 1 ; return 0 ; } void fk(int x , int y ,int dir) { if(fkk == 0)return ; if(!inmap(x , y))return ; if(T[fkk].count) { ans[T[fkk].count].s = s ; ans[T[fkk].count].e = e ; ans[T[fkk].count].fk = char(dir + 'A') ; // T[fkk].count = 0 ;//这里加不加都可以,反正是spj,加了速度快一点 // return ; //切记不要return } int next = Map[x + mx[dir]][y + my[dir]] - 'A' ; fkk = T[fkk].next[next] ; if(inmap(x + mx[dir] , y + my[dir])) fk(x + mx[dir] , y + my[dir] , dir) ; } char fk1[1111] ; int main() { int xx ; while(cin >> n >> m >> xx ) { init() ; for (int i = 0 ; i < n ; i ++ )scanf("%s",Map[i]) ; for (int i = 1 ; i <= xx ; i ++ ) { scanf("%s",fk1) ; insert(fk1 , i) ; } for (int i = 0 ; i < n ; i ++ ) { for (int j = 0 ; j < m ; j ++ ) { for (int k = 0 ; k < 8 ; k ++ ) { s = i ; e = j ; fkk = T[0].next[Map[i][j] - 'A'] ; if(!fkk)break ; fk(i , j , k) ; } } } for (int i = 1 ; i <= xx ; i ++ ) { printf("%d %d ",ans[i].s , ans[i].e) ; putchar(ans[i].fk) ;putchar('\n') ; } } return 0 ; }
作者:kdqzzxxcc 发表于2013-8-30 19:05:01 原文链接
阅读:49 评论:0 查看评论