bzoj 4327 AC自动机
思路:将能跑到的状态标记一下,在bfs搜一下就好啦。
#include<bits/stdc++.h> #define LL long long #define ll long long #define fi first #define se second #define mk make_pair #define PII pair<int, int> #define y1 skldjfskldjg #define y2 skldfjsklejg using namespace std; const int N = 1e7 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1000000007; int n, m, len[100007], pos[100007]; char s[N], t[101]; struct Ac { int ch[N][4], f[N], d[N], tot, sz; Ac(int sz) {this->sz = sz;} void init() {tot = 0;} int newNode() { tot++; f[tot] = 0; memset(ch[tot], 0, sizeof(ch[tot])); return tot; } inline int idx(char c) { if(c == 'E') return 0; if(c == 'S') return 1; if(c == 'W') return 2; if(c == 'N') return 3; } void addStr(char *s, int ID) { int u = 0; for(int i = 0; s[i]; i++) { int c = idx(s[i]); if(!ch[u][c]) ch[u][c] = newNode(); u = ch[u][c]; } pos[ID] = u; } void build() { queue<int> que; for(int c = 0; c < sz; c++) { int v = ch[0][c]; if(!v) ch[0][c] = 0; else f[v] = 0, que.push(v); } while(!que.empty()) { int u = que.front(); que.pop(); for(int c = 0; c < sz; c++) { int v = ch[u][c]; if(!v) ch[u][c] = ch[f[u]][c]; else f[v] = ch[f[u]][c], que.push(v); } } } void solve(char *s) { queue<int> que; memset(d, -1, sizeof(d)); int u = 0; d[u] = 0; que.push(u); for(int i = 0; s[i]; i++) { int c = idx(s[i]); u = ch[u][c]; int p = u; while(p && d[p] == -1) { d[p] = 0; que.push(p); p = f[p]; } } while(!que.empty()) { int u = que.front(); que.pop(); for(int c = 0; c < sz; c++) { int v = ch[u][c]; if(d[v] != -1) continue; d[v] = d[u] + 1; que.push(v); } } for(int i = 1; i <= m; i++) printf("%d\n", len[i] - d[pos[i]]); } } ac(4); int main() { ac.init(); scanf("%d%d", &n, &m); scanf("%s", s); for(int i = 1; i <= m; i++) { scanf("%s", t); ac.addStr(t, i); len[i] = strlen(t); } ac.build(); ac.solve(s); return 0; } /* */