社区讨论

我的 AC 自动机被熨斗卡常了怎么办

P14363[CSP-S 2025] 谐音替换参与者 5已保存回复 5

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
5 条
当前快照
1 份
快照标识符
@mhixqs2c
此快照首次捕获于
2025/11/03 17:26
4 个月前
此快照最后确认于
2025/11/08 07:51
4 个月前
查看原帖
RT,95pts。
代码CPP
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200010, L = 5000010, W = 30;
const ll mod = 2025110249ll;
mt19937 rng (114514);
uniform_int_distribution <ll> dist (1919810ll, mod - 1919810ll);
int n, m, q, w = 27, a[L], cnt;
ll bas[L];
char s[L], t[L];
map <ll, int> mp;
namespace ac {
	int nxt[L][W], fail[L], dat[L], tcnt;
	void insert (int p) {
		for (int i = 1; i <= cnt; i++) {
			if (nxt[p][a[i]] == 0) {
				nxt[p][a[i]] = ++tcnt;
			}
			p = nxt[p][a[i]];
		}
		dat[p]++;
	}
	queue <int> q;
	void getfail (int p) {
		for (int i = 1; i <= w; i++) {
			if (nxt[p][i] != 0) {
				fail[nxt[p][i]] = p;
				q.push (nxt[p][i]);
			} else {
				nxt[p][i] = p;
			}
		}
		while (!q.empty ()) {
			int u = q.front ();
			q.pop ();
			for (int i = 1; i <= w; i++) {
				if (nxt[u][i] == 0) {
					nxt[u][i] = nxt[fail[u]][i];
				} else {
					fail[nxt[u][i]] = nxt[fail[u]][i];
					q.push (nxt[u][i]);
				}
			}
		}
	}
	int query (int p) {
		int ret = 0;
		for (int i = 1; i <= cnt; i++) {
			p = nxt[p][a[i]];
			for (int j = p; j != 0; j = fail[j]) {
				ret += dat[j];
			}
		}
		return ret;
	}
}
int main () {
	freopen ("replace.in", "r", stdin);
	freopen ("replace.out", "w", stdout);
	scanf ("%d%d", &n, &q);
	for (int i = 1; i <= n; i++) {
		scanf ("%s%s", s + 1, t + 1);
		m = strlen (s + 1);
		int l = -1, r = -1;
		for (int j = 1; j <= m; j++) {
			if (s[j] != t[j]) {
				if (l == -1) {
					l = j;
				}
				r = j;
			}
		}
		if (l == -1 && r == -1) {
			continue;
		}
		ll hsh = 0;
		for (int j = l; j <= r; j++) {
			if (bas[j - l + 1] == 0) {
				bas[j - l + 1] = dist (rng);
			}
			ll u = (s[j] - 96) * 26 + t[j] - 96;
			(hsh += u * bas[j - l + 1]) %= mod;
		}
		cnt = 0;
		for (int j = 1; j <= m; j++) {
			if (j == l) {
				a[++cnt] = 27;
			}
			if (j >= l && j <= r) {
				continue;
			}
			a[++cnt] = s[j] - 96;
		}
		int t = 0;
		if (mp.count (hsh)) {
			t = mp[hsh];
		} else {
			t = mp[hsh] = ++ac::tcnt;
		}
		ac::insert (t);
	}
	for (auto i : mp) {
		ac::getfail (i.second);
	}
	for (int i = 1; i <= q; i++) {
		scanf ("%s%s", s + 1, t + 1);
		m = strlen (s + 1);
		if (strlen (t + 1) != m) {
			puts ("0");
			continue;
		}
		int l = -1, r = -1;
		for (int j = 1; j <= m; j++) {
			if (s[j] != t[j]) {
				if (l == -1) {
					l = j;
				}
				r = j;
			}
		}
		ll hsh = 0;
		for (int j = l; j <= r; j++) {
			if (bas[j - l + 1] == 0) {
				bas[j - l + 1] = dist (rng);
			}
			int u = (s[j] - 96) * 26 + t[j] - 96;
			(hsh += u * bas[j - l + 1]) %= mod;
		}
		if (!mp.count (hsh)) {
			puts ("0");
		} else {
			cnt = 0;
			for (int j = 1; j <= m; j++) {
				if (j == l) {
					a[++cnt] = 27;
				}
				if (j >= l && j <= r) {
					continue;
				}
				a[++cnt] = s[j] - 96;
			}
			printf ("%d\n", ac::query (mp[hsh]));
		}
	}
	return 0;
}
求问是熨斗评测机问题还是数据强度问题。
另外如果 AC 自动机可过这题岂不是要降蓝

回复

5 条回复,欢迎继续交流。

正在加载回复...