翻译洛谷有,但输入格式好像不太一样,注意一下。
这题我看了5分钟才把题看懂,知道是有关AC自动机的,然而就是想不出来。
我一直觉得应该把这张图建一个trie树,毕竟图作为主串,然后看模式串是否出现在主串里。
然而实际上是模式串建trie树。
然后题中说要判断8个方向是否有模式串出现,那么就把图中8个方向形成的字符串都放到AC自动机上跑一下。我刚开始以为会超时,但复杂度最多为O(8 * n2),只有8e6,而AC自动机是线性的,所以TLE不了。
关于遍历八个方向上的字符串,写起来得动动脑子,可以联想到bfs或dfs跑图的时候用到的方向数组。
然后有因为AC自动机找到的匹配点是模式串的末尾,所以我们还要在这个方向上减去模式串的长度。
然后就是AC自动机的板子了。
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<stack> 9 #include<queue> 10 #include<vector> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(‘ ‘) 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 1e3 + 5; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), las = ‘ ‘; 25 while(!isdigit(ch)) las = ch, ch = getchar(); 26 while(isdigit(ch)) ans = ans * 10 + ch - ‘0‘, ch = getchar(); 27 if(las == ‘-‘) ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) putchar(‘-‘), x = -x; 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + ‘0‘); 35 } 36 37 int n, m, w; 38 char a[maxn][maxn], s[maxn]; 39 40 int len[maxn]; 41 int ch[maxn * maxn][26], val[maxn * maxn], f[maxn * maxn], cnt = 0; 42 int getnum(char c) 43 { 44 return c - ‘A‘; 45 } 46 void insert(int id, char *s) 47 { 48 len[id] = strlen(s); 49 int now = 0; 50 for(int i = 0; i < len[id]; ++i) 51 { 52 int c = getnum(s[i]); 53 if(!ch[now][c]) ch[now][c] = ++cnt; 54 now = ch[now][c]; 55 } 56 val[now] = id; 57 } 58 void build() 59 { 60 queue<int> q; 61 for(int i = 0; i < 26; ++i) if(ch[0][i]) q.push(ch[0][i]); 62 while(!q.empty()) 63 { 64 int now = q.front(); q.pop(); 65 for(int i = 0; i < 26; ++i) 66 { 67 if(ch[now][i]) f[ch[now][i]] = ch[f[now]][i], q.push(ch[now][i]); 68 else ch[now][i] = ch[f[now]][i]; 69 } 70 } 71 } 72 const int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1}, dy[] = {0, 1, 1, 1, 0, -1, -1, -1}; 73 struct Node 74 { 75 int x, y, d; 76 }ans[maxn]; 77 void query(int x, int y, int d) 78 { 79 int newx = x, newy = y, now = 0; 80 do 81 { 82 int c = getnum(a[newx][newy]); 83 now = ch[now][c]; 84 for(int j = now; j && val[j] != -1; j = f[j]) if(val[j] > 0) 85 { 86 ans[val[j]].x = newx - (len[val[j]] - 1) * dx[d]; 87 ans[val[j]].y = newy - (len[val[j]] - 1) * dy[d]; 88 ans[val[j]].d = d; 89 val[j] = -1; 90 } 91 newx += dx[d]; newy += dy[d]; 92 }while(newx >= 0 && newx < n && newy >= 0 && newy < m); 93 } 94 95 int main() 96 { 97 n = read(); m = read(); w = read(); 98 for(int i = 0; i < n; ++i) scanf("%s", a[i]); 99 for(int i = 1; i <= w; ++i) 100 { 101 scanf("%s", s); 102 insert(i, s); 103 } 104 build(); 105 for(int i = 0; i < n; ++i) 106 { 107 query(i, 0, 2); query(i, m - 1, 6); 108 query(i, 0, 1); query(i, m - 1, 5); 109 query(i, 0, 3); query(i, m - 1, 7); 110 } 111 for(int i = 0; i < m; ++i) 112 { 113 query(n - 1, i, 0); query(0, i, 4); 114 query(n - 1, i, 1); query(0, i, 5); 115 query(0, i, 3); query(n - 1, i, 7); 116 } 117 for(int i = 1; i <= w; ++i) printf("%d %d %c\n", ans[i].x, ans[i].y, ans[i].d + ‘A‘); 118 return 0; 119 }
原文:https://www.cnblogs.com/mrclr/p/9769911.html