不是很懂,ac自动机模板题简单版不是就可以直接暴力跳fail吗,像这样:
int query(string s) {
int l = s.size(), u = 1, ret = 0; s = '0' + s;
for (int i = 1; i <= l; ++i) {
int c = s[i] - 'a', v = tr[u][c];
while(v > 1 && tag[v] != -1) {
ret += tag[v], tag[v] = -1;
v = fail[v];
}
u = tr[u][c];
}
return ret;
}
那这个的复杂度到底是多少呢?然后这个题中这样暴力跳就会 TLE 66pts,不是很理解为什么:
auto query(std::string s) {
auto n = (int)s.size(), u = 0;
for (auto i = 0; i < n; ++i) {
auto v = u = tr[u][s[i] - 'a'];
while (v && !tag[v]) v = nxt[v];
ans[++m] = s[i];
if (tag[v]) u = pos[m -= len[v]];
else pos[m] = u;
}
for (auto i = 1; i <= m; ++i) cout << ans[i];
return ;
}
而我在题解中发现了一种保留上次跳的过程的优化跳fail方式,虽然不理解为什么这样跑是对的,但是为什么这更快,可以AC?它的复杂度又是什么呢?
auto query(std::string s) {
auto n = (int)s.size(), u = 0;
for (auto i = 0; i < n; ++i) {
auto k = s[i] - 'a';
while (u && !tr[u][k]) u = nxt[u];
if (tr[u][k]) u = tr[u][k];
ans[++m] = s[i];
if (tag[u]) u = pos[m -= len[u]];
else pos[m] = u;
}
for (auto i = 1; i <= m; ++i) cout << ans[i];
return ;
}
而我在AC自动机模板题简单版中试着也这样优化跳fail,却连样例都是错的,这又是为什么呢??
auto query(std::string s) {
auto n = (int)s.size(), u = 0;
for (auto i = 0; i < n; ++i) {
auto k = s[i] - 'a';
while (u && !tr[u][k]) u = nxt[u];
if (tr[u][k]) u = tr[u][k];
auto v = u;
while (v && tag[v] != -1)
ans += tag[v], tag[v] = -1;
}
cout << ans << "\n";
return ;
}
本人真的完全不会字符串,求大佬解答/kel