constint N = 500010; constint MOD = 20071027; constint INF = 0x3fffffff;
structTrie {int ch[30], tag;} t[N];
int cnt, n, f[N], T; char s[N];
inlinevoidinsert(char *S){ int p = 0, len = strlen(S); for (int i = 0; i < len; ++ i) { int k = S[i] - 'a'; if (!t[p].ch[k]) t[p].ch[k] = ++ cnt; p = t[p].ch[k]; } t[p].tag |= true; }
inlinevoidclear(){ for (int i = 0; i <= cnt; ++ i) { for (int j = 0; j < 26; ++ j) t[i].ch[j] = 0; t[i].tag = 0; } mset(f, 0); cnt = 0; }
intmain(){ while (scanf("%s", s) != EOF) { clear(); scanf("%d", &n); for (int i = 1; i <= n; ++ i) { char S[N]; scanf("%s", S); insert(S); } int len = strlen(s); f[len] = 1; for (int i = len - 1; i >= 0; -- i) { int p = 0; for (int j = i; j < len; ++ j) { int k = s[j] - 'a'; if (!t[p].ch[k]) break; else p = t[p].ch[k]; if (t[p].tag) (f[i] += f[j + 1]) %= MOD; } } printf("Case %d: %d\n", ++ T, f[0]); } return0; }
#define ll long long #define ull unsigned long long #define mset(l,x) memset(l,x,sizeof(l))
constint N = 600010; const ull BASE = 131; constint INF = 0x3fffffff;
char s[N], t[N]; int n, m, k, prep[N], sufp[N]; ull hs[N], ht[N], p[N];
inline ull Gethash(ull hash[], int l, int len){ return hash[l + len - 1] - hash[l - 1] * p[len]; }
intmain(){ scanf("%d%d%d", &n, &m, &k); scanf("%s%s", s + 1, t + 1); p[0] = 1; for (int i = 1; i <= n; ++ i) hs[i] = hs[i - 1] * BASE + (ull)(s[i] - 'a' + 1); for (int i = 1; i <= m; ++ i) ht[i] = ht[i - 1] * BASE + (ull)(t[i] - 'a' + 1); for (int i = 1; i <= n; ++ i) p[i] = p[i - 1] * BASE; mset(prep, -1); mset(sufp, -1); for (int x = 1, l = 1; x <= m; ++ x) { while (l + x - 1 <= n && Gethash(hs, l, x) != ht[x]) ++ l; if (l + x - 1 <= n) prep[x] = l + x - 1; elsebreak; } for (int x = 1, l = k; x < m; ++ x) { if (prep[x] >= k || prep[x] == -1) break; while (l <= n && (x > l || Gethash(hs, l - x + 1, x) != ht[x])) ++ l; if (l <= n) prep[x] = l; else prep[x] = -1; } prep[0] = k; if (~prep[m]) prep[m] = max(prep[m], k); for (int x = 1, l = n; x <= m; ++ x) { while (l - x + 1 >= 1 && Gethash(hs, l - x + 1, x) != Gethash(ht, m - x + 1, x)) -- l; if (l - x + 1 >= 1) sufp[m - x + 1] = l - x + 1; elsebreak; } for (int x = 1, l = n - k + 1; x < m; ++ x) { if (sufp[m - x + 1] <= n - k + 1 || sufp[m - x + 1] == -1) break; while (l >= 1 && (l > n - x + 1 || Gethash(hs, l, x) != Gethash(ht, m - x + 1, x))) -- l; if (l >= 1) sufp[m - x + 1] = l; else sufp[m - x + 1] = -1; } if (~sufp[1]) sufp[1] = min(sufp[1], n - k + 1); sufp[m + 1] = n - k + 1; for (int i = 0; i <= m; ++ i) { if (prep[i] == -1 || sufp[i + 1] == -1) continue; if (prep[i] >= sufp[i + 1]) continue; if (i > k || m - i > k) continue; if (i != 0 && i != m) if (prep[i] < k || n - sufp[i + 1] + 1 < k) continue; printf("Yes\n%d %d", prep[i] - k + 1, sufp[i + 1]); return0; } printf("No"); return0; }
inlineAC(){cnt = 0;} inlinevoidinsert(char *s){ int p = 0, len = strlen(s); for (int i = 0; i < len; ++ i) { int k = s[i] - 'A'; if (!t[p].ch[k]) t[p].ch[k] = ++ cnt; p = t[p].ch[k]; } t[p].tag |= true; }
inlinevoidbuild(){ queue <int> q; for (int i = 0; i < 26; ++ i) if (t[0].ch[i]) q.push(t[0].ch[i]); while (q.size()) { int now = q.front(); q.pop(); for (int i = 0; i < 26; ++ i) if (t[now].ch[i]) { t[t[now].ch[i]].fail = t[t[now].fail].ch[i]; t[t[now].ch[i]].tag |= t[t[t[now].fail].ch[i]].tag; q.push(t[now].ch[i]); } else t[now].ch[i] = t[t[now].fail].ch[i]; } } } ac;
int n, m, f[N][N], ans; char s[N];
inlineintfpow(int a, int b){ int res = 1; while (b) { if (b & 1) (res *= a) %= MOD; b >>= 1, (a *= a) %= MOD; } return res; }
intmain(){ scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++ i) scanf("%s", s), ac.insert(s); ac.build(); f[0][0] = 1; for (int i = 1; i <= m; ++ i) for (int j = 0; j <= ac.cnt; ++ j) for (int k = 0; k < 26; ++ k) if (!ac.t[ac.t[j].ch[k]].tag) (f[i][ac.t[j].ch[k]] += f[i - 1][j]) %= MOD; for (int i = 0; i <= ac.cnt; ++ i) (ans += f[m][i]) %= MOD; printf("%d", (fpow(26, m) - ans + MOD) % MOD); return0; }
#Prob. 5 [HEOI2012]旅行问题
Time Limit: s | Memory Limit: MB
#大体思路
不难发现我们要找的也就是两个串的最长公共后缀,这与 AC 自动机 fail 边所指向的节点的定义相吻合,于是只需要找到建出 AC 自动机的 fail 树,找到对应的 LCA 即可。
constint N = 1000010; constint MOD = 1e9 + 7; constint INF = 0x3fffffff;
structEdge {int u, v, nxt;} e[N]; structTrie {int ch[26], fail;};
int n, ecnt = 1, head[N], m; ll ans[N]; vector<int> ds[N];
inlinevoidadd(int u, int v){ e[ecnt].u = u, e[ecnt].v = v; e[ecnt].nxt = head[u], head[u] = ecnt ++; }
structAC_automaton { Trie t[N]; int cnt;
inlineAC_automaton(){cnt = 0, t[0].fail = -1;} inlinevoidinsert(char *s, int id){ int p = 0, len = strlen(s); ds[id].push_back(0); for (int i = 0; i < len; ++ i) { int k = s[i] - 'a'; if (!t[p].ch[k]) { t[p].ch[k] = ++ cnt; ans[cnt + 1] = (ans[p + 1] * 26 % MOD + (ll)k) % MOD; } p = t[p].ch[k]; ds[id].push_back(p + 1); } }
inlinevoidbuild(){ queue <int> q; for (int i = 0; i < 26; ++ i) if (t[0].ch[i]) q.push(t[0].ch[i]); while (q.size()) { int now = q.front(); q.pop(); for (int i = 0; i < 26; ++ i) if (t[now].ch[i]) { t[t[now].ch[i]].fail = t[t[now].fail].ch[i]; q.push(t[now].ch[i]); } else t[now].ch[i] = t[t[now].fail].ch[i]; } }
inlinevoidbuild_tree(){ for (int i = 1; i <= cnt; ++ i) add(t[i].fail + 1, i + 1); } } ac;
int dfn[N], son[N], siz[N], top[N], T, f[N], d[N];
voiddfs1(int x, int fa){ siz[x] = 1, f[x] = fa, d[x] = d[fa] + 1; for (int i = head[x]; i; i = e[i].nxt) if (e[i].v != fa) { dfs1(e[i].v, x); siz[x] += siz[e[i].v]; if (siz[e[i].v] > siz[son[x]]) son[x] = e[i].v; } }
voiddfs2(int x, int t){ dfn[x] = ++ T, top[x] = t; if (!son[x]) {return;} dfs2(son[x], t); for (int i = head[x]; i; i = e[i].nxt) if (e[i].v != f[x] && e[i].v != son[x]) dfs2(e[i].v, e[i].v); }
inlineintLCA(int a, int b){ while (top[a] != top[b]) { if (d[top[a]] < d[top[b]]) swap(a, b); a = f[top[a]]; } if (d[a] < d[b]) {swap(a, b);} return b; }
intmain(){ scanf("%d", &n); char s[N]; for (int i = 1; i <= n; ++ i) { scanf("%s", s); ac.insert(s, i); } ac.build(); ac.build_tree(); dfs1(1, 0); dfs2(1, 1); scanf("%d", &m); while (m --) { int i, j, k, l; scanf("%d%d%d%d", &i, &j, &k, &l); int lca = LCA(ds[i][j], ds[k][l]); printf("%d\n", ans[lca]); } return0; }