关于AC自动机跳fail
查看原帖
关于AC自动机跳fail
483928
Z1qqurat楼主2023/12/28 21:24

不是很懂,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

2023/12/28 21:24
加载中...