pyyz集训day8

https://files.cnblogs.com/files/blogs/832279/814.zip?t=1786666903&download=true
献上代码:

1.Isomorphic Strings

点击查看代码
#include <iostream>

using std::cin;
using std::cout;
typedef long long ll;
typedef unsigned ui;
const int N = 2e5 + 10;
const int mod = 1e9 + 11;
const int bas1 = 1333331;
const ui bas2 = 1333331;

int pos[27];
char s[N];
int pre[N];
int pow1[N];
ui pow2[N];
int hsh1[N];
int suf[N][27];
ui hsh2[N];

int get1(int l, int r)
{
	return ((1ll * hsh1[r] - 1ll * hsh1[l - 1] * pow1[r - l + 1] % mod) % mod + mod) % mod;
}
ui get2(int l, int r)
{
	return hsh2[r] - hsh2[l - 1] * pow2[r - l + 1];
}
int gt1(int l, int r)
{
	int ret1 = get1(l, r);
	for (int i = 1; i <= 26; ++i)
	{
		if (suf[l][i] && suf[l][i] <= r)
			ret1 = ((ret1 - 1ll * pow1[r - suf[l][i]] * pre[suf[l][i]] % mod) % mod + mod) % mod;
	}
	return ret1;
}
ui gt2(int l, int r)
{
	ui ret2 = get2(l, r);
	for (int i = 1; i <= 26; ++i)
	{
		if (suf[l][i] && suf[l][i] <= r)
			ret2 = ret2 - pow2[r - suf[l][i]] * pre[suf[l][i]];
	}
	return ret2;
}

int main()
{
	int n, m;
	cin >> n >> m;
	cin >> (s + 1);
	pow1[0] = pow2[0] = 1;
	for (int i = 1; i <= n; ++i)
	{
		pow1[i] = 1ll * pow1[i - 1] * bas1 % mod;
		pow2[i] = pow2[i - 1] * bas2;
		pre[i] = i - pos[s[i] - 'a' + 1] + 1;
		pos[s[i] - 'a' + 1] = i;
		hsh1[i] = (1ll * hsh1[i - 1] * bas1 % mod + pre[i]) % mod;
		hsh2[i] = hsh2[i - 1] * bas2 + pre[i];
	}
	for (int i = 1; i <= 26; ++i)
		pos[i] = 0;
	for (int i = n; i >= 1; --i)
	{
		pos[s[i] - 'a' + 1] = i;
		for (int j = 1; j <= 26; ++j)
			suf[i][j] = pos[j];
	}
	for (int i = 1; i <= m; ++i)
	{
		int x, y, l;
		cin >> x >> y >> l;
		if (gt1(x, x + l - 1) == gt1(y, y + l - 1) && gt2(x, x + l - 1) == gt2(y, y + l - 1))
			cout << "YES" << '\n';
		else
			cout << "NO" << '\n';
	}
	return 0;
}

2.PRE-Prefixuffix

点击查看代码
#include <iostream>

using std::cin;
using std::cout;
const int N = 1e6 + 10;
const int bas1 = 1331;
const int bas2 = 131;
const int mod1 = 13178911;
const int mod2 = 998244353;

char t[N];
int hsh1[N];
int hsh2[N];
int pow1[N];
int pow2[N];

int get1(int l, int r)
{
	return (hsh1[r] - 1ll * hsh1[l - 1] * pow1[r - l + 1] % mod1 + mod1) % mod1;
}
int get2(int l, int r)
{
	return (hsh2[r] - 1ll * hsh2[l - 1] * pow2[r - l + 1] % mod2 + mod2) % mod2;
}

int main()
{
	int n;
	cin >> n;
	cin >> (t + 1);
	pow1[0] = pow2[0] = 1;
	for (int i = 1; i <= n; ++i)
	{
		pow1[i] = 1ll * pow1[i - 1] * bas1 % mod1;
		pow2[i] = 1ll * pow2[i - 1] * bas2 % mod2;
		hsh1[i] = (1ll * hsh1[i - 1] * bas1 % mod1 + t[i] - 'a' + 1) % mod1;
		hsh2[i] = (1ll * hsh2[i - 1] * bas2 % mod2 + t[i] - 'a' + 1) % mod2;
	}
	int k = 0;
	int ans = 0;
	for (int j = n / 2; j >= 1; --j)
	{
		while (j + k >= n - j + 1 - k)
			k--;
		while (get1(j + 1, j + k) != get1(n - j + 1 - k, n - j) || get2(j + 1, j + k) != get2(n - j + 1 - k, n - j))
			k--;
		if (get1(1, j) == get1(n - j + 1, n) && get2(1, j) == get2(n - j + 1, n))
			ans = std::max(ans, j + k);
		k = k + 2;
	}
	cout << ans << '\n';
	return 0;
}

ps:一定要从大到小枚举原串公共前后缀的长度。

3.神牛的养成计划

点击查看代码
#include <iostream>
#include <string>
#include <vector>
#include <map>
#define lowbit(x) x & (-x)
#include <bits/stdc++.h>

using std::cin;
using std::cout;
using namespace std;
const int N = 2e6 + 10;
const int M = 2e3 + 10;

int tot1 = 1;
int tot2 = 1;
int idx1, idx2;
int pos1[N];
int pos2[N];
int ld1[N];
int rd1[N];
int ld2[N];
int rd2[N];
int sum[M][M];
std::string s;
std::string s1;
std::map<int, int> son1[N];
std::map<int, int> son2[N];
set<int> st1, st2;

void add(int x, int y, int k)
{
	for (int i = x; i <= idx1; i += lowbit(i))
	{
		for (int j = y; j <= idx2; j += lowbit(j))
			sum[i][j] += k;
	}
}
int query(int x, int y)
{
	int ret = 0;
	for (int i = x; i; i -= lowbit(i))
	{
		for (int j = y; j; j -= lowbit(j))
			ret += sum[i][j];
	}
	return ret;
}
void ins1(int id)
{
	int now = 1;
	for (auto c : s)
	{
		int k = c - 'a' + 1;
		if (!son1[now][k])
			son1[now][k] = ++tot1;
		now = son1[now][k];
	}
	pos1[id] = now;
	st1.insert(now);
}
void ins2(int id)
{
	int now = 1;
	for (auto i = s.rbegin(); i != s.rend(); ++i)
	{
		char c = *i;
		int k = c - 'a' + 1;
		if (!son2[now][k])
			son2[now][k] = ++tot2;
		now = son2[now][k];
	}
	pos2[id] = now;
	st2.insert(now);
}
void dfs1(int x)
{
	ld1[x] = numeric_limits<int>::max();
	rd1[x] = numeric_limits<int>::min();
	if (st1.lower_bound(x) != st1.end() && 
	  (*(st1.lower_bound(x))) == x) 
		ld1[x] = ++idx1, rd1[x] = idx1;
	for (auto it : son1[x])
	{
		dfs1(it.second);
		ld1[x] = min(ld1[x], ld1[it.second]);
		rd1[x] = std::max(rd1[x], rd1[it.second]);
	}
}
void dfs2(int x)
{
	ld2[x] = numeric_limits<int>::max();
	rd2[x] = numeric_limits<int>::min();
	if (st2.lower_bound(x) != st2.end() && 
	  (*(st2.lower_bound(x))) == x)
		ld2[x] = ++idx2, rd2[x] = idx2;
	for (auto it : son2[x])
	{
		dfs2(it.second);
		ld2[x] = min(ld2[x], ld2[it.second]);
		rd2[x] = std::max(rd2[x], rd2[it.second]);
	}
}
int get1()
{
	int now = 1;
	for (auto c : s)
	{
		int k = c - 'a' + 1;
		if (!son1[now].count(k))
			return 0;
		now = son1[now][k];
	}
	return now;
}
int get2()
{
	int now = 1;
	for (auto i = s1.rbegin(); i != s1.rend(); ++i)
	{
		char c = *i;
		int k = c - 'a' + 1;
		if (!son2[now].count(k))
			return 0;
		now = son2[now][k];
	}
	return now;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; ++i)
	{
		cin >> s;
		ins1(i), ins2(i);
	}
	dfs1(1);
	dfs2(1);
	for (int i = 1; i <= n; ++i) {
		add(ld1[pos1[i]], ld2[pos2[i]], 1);
	}
	int m;
	cin >> m;
	int last = 0;
	for (int i = 1; i <= m; ++i)
	{
		cin >> s;
		cin >> s1;
		for (auto &k : s) {
			k = (k - 'a' + last) % 26 + 'a';
		}
		for (auto &k : s1) {
			k = (k - 'a' + last) % 26 + 'a';
		}
		int pr = get1();
		int sf = get2();
		if (pr == 0 || sf == 0) {
			cout << 0 << "\n";
		}
		else
			cout << (last = query(rd1[pr], rd2[sf]) - query(rd1[pr], ld2[sf] - 1) 
			- query(ld1[pr] - 1, rd2[sf]) + query(ld1[pr] - 1, ld2[sf] - 1)) << '\n';
	}
	return 0;
}

ps:毒瘤出题人卡空间,要用map维护trie树上儿子的信息。

4.Scissors

点击查看代码
#include <iostream>

using std::cin;
using std::cout;
const int N = 5e5 + 10;

char s[N];
char t[N];
int nxt1[N];
int nxt2[N];
int mn[N];
int mx[N];

int main()
{
	int n, m, k;
	cin >> n >> m >> k;
	cin >> (s + 1);
	cin >> (t + 1);
	int j = 0;
	for (int i = 2; i <= m; ++i)
	{
		while (j && t[j + 1] != t[i])
			j = nxt1[j];
		if (t[j + 1] == t[i])
			j++;
		nxt1[i] = j;
	}
	j = 0;
	for (int i = 1; i <= n; ++i)
	{
		while (j && t[j + 1] != s[i])
			j = nxt1[j];
		if (t[j + 1] == s[i])
			j++;
		if (i >= k)
		{
			int p = j;
			while (p && !mn[p])
			{
				mn[p] = i;
				p = nxt1[p];
			}
		}
		if (j == m)
		{
			if (m <= k)
			{
				int l = std::max(1, i - k + 1);
				int r = l + k - 1;
				if (r <= n - k)
				{
					cout << "Yes" << '\n';
					cout << l << ' ' << n - k + 1 << '\n';
					return 0;
				}
				r = std::min(n, i - m + k);
				l = r - k + 1;
				if (l > k)
				{
					cout << "Yes" << '\n';
					cout << 1 << ' ' << l << '\n';
					return 0;
				}
			}
			j = nxt1[j];
		}
	}
	j = m + 1;
	nxt2[m] = m + 1;
	for (int i = m - 1; i >= 1; --i)
	{
		while (j != m + 1 && t[j - 1] != t[i])
			j = nxt2[j];
		if (t[j - 1] == t[i])
			j--;
		nxt2[i] = j;
	}
	j = m + 1;
	for (int i = n; i >= 1; --i)
	{
		while (j != m + 1 && t[j - 1] != s[i])
			j = nxt2[j];
		if (t[j - 1] == s[i])
			j--;
		if (i <= n - k + 1)
		{
			int p = j;
			while (p != m + 1 && !mx[p])
			{
				mx[p] = i;
				p = nxt2[p];
			}
		}
		if (j == 1)
			j = nxt2[j];
	}
	for (int i = 1; i < m; ++i)
	{
		if (mn[i] && mx[i + 1] && mn[i] < mx[i + 1] && i <= k && m - i <= k)
		{
			cout << "Yes" << '\n';
			cout << mn[i] - k + 1 << ' ' << mx[i + 1] << '\n';
			return 0;
		}
	}
	if (mn[m] && m <= k && mn[m] <= n - k)
	{
		cout << "Yes" << '\n';
		cout << mn[m] - k + 1 << ' ' << n - k + 1 << '\n';
	}
	else
		cout << "No" << '\n';
	return 0;
}

ps:这个题有许多要特判的地方。

5.CHO-Hamsters

点击查看代码
#include <iostream>
#include <cstring>
#include <string>

using std::cin;
using std::cout;
const int N = 210;
typedef long long ll;
struct Mat
{
	int n, m;
	ll a[N][N];
	Mat()
	{
		memset(a, 0x3f, sizeof(a));
	}
	void init(int x)
	{
		Mat();
		n = m = x;
		for (int i = 1; i <= x; ++i)
			a[i][i] = 0;
	}
	friend Mat operator*(const Mat &a, const Mat &b)
	{
		Mat ret;
		ret.n = a.n;
		ret.m = b.m;
		for (int i = 1; i <= a.n; ++i)
		{
			for (int j = 1; j <= a.m; ++j)
			{
				for (int k = 1; k <= b.m; ++k)
					ret.a[i][k] = std::min(ret.a[i][k], a.a[i][j] + b.a[j][k]);
			}
		}
		return ret;
	}
} k, fst, ret;

int nxt[(int)2e5 + 10];
std::string s[N];

void ksm(int x)
{
	for (; x; k = k * k, x >>= 1)
	{
		if (x & 1)
			ret = ret * k;
	}
}

int main()
{
	int n, m;
	cin >> n >> m;
	k.n = k.m = n;
	ret.init(n);
	fst.n = 1, fst.m = n;
	for (int i = 1; i <= n; ++i)
		cin >> s[i];
	for (int i = 1; i <= n; ++i)
	{
		for (int j = 0; j < s[i].size(); ++j)
			nxt[j] = -1;
		int p = -1;
		for (int j = 1; j < s[i].size(); ++j)
		{
			while (p != -1 && s[i][p + 1] != s[i][j])
				p = nxt[p];
			if (s[i][p + 1] == s[i][j])
				p++;
			nxt[j] = p;
		}
		for (int j = 1; j <= n; ++j)
		{
			if (i == j)
			{
				k.a[i][j] = s[i].size() - (nxt[s[i].size() - 1] + 1);
				continue;
			}
			int p = -1;
			for (int k = 0; k < s[j].size(); ++k)
			{
				while (p != -1 && s[i][p + 1] != s[j][k])
					p = nxt[p];
				if (s[i][p + 1] == s[j][k])
					p++;
			}
			k.a[j][i] = s[i].size() - p - 1;
		}
	}
	for (int i = 1; i <= n; ++i)
		fst.a[1][i] = s[i].size();
	ksm(m - 1);
	fst = fst * ret;
	ll ans = 1e18;
	for (int i = 1; i <= n; ++i)
		ans = std::min(ans, fst.a[1][i]);
	cout << ans << '\n';
	return 0;
}

6.Message

点击查看代码
#include <iostream>
#include <cstring>
#include <vector>

using std::cin;
using std::cout;
const int N = 2e5 + 10;
typedef long long ll;
const ll oo = 1e18;

int tot;
int idx;
bool app[27];
int al[27];
int cnt[27];
char s[N];
char t[N];
char ns[N];
int w[N];
int l[N];
int r[N];
int id[N];
int nxt[N];
int vis[N];
ll sum1[N];
ll sum2[N];
ll f[N][56];

int main()
{
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> (s + 1);
	cin >> (t + 1);
	int n = strlen(s + 1);
	int m = strlen(t + 1);
	for (int i = 1; i <= m; ++i)
		al[t[i] - 'a' + 1]++;
	for (int i = 1; i <= m; ++i)
	{
		cnt[t[i] - 'a' + 1]++;
		if (cnt[t[i] - 'a' + 1] == 1)
			vis[i] += 1;
		if (cnt[t[i] - 'a' + 1] == al[t[i] - 'a' + 1])
			vis[i] += 2;
	}
	for (int i = 1; i <= m; ++i)
	{
		if ((vis[i] & 1) && (i == 1 || !(vis[i - 1] & 2)))
		{
			++idx;
			l[idx] = i;
			r[idx] = i;
		}
		if ((vis[i] & 2) && i < m)
		{
			r[idx] = i;
			++idx;
			l[idx] = i + 1;
			r[idx] = i + 1;
		}
		if ((vis[i] & 2) && i == m)
			r[idx] = m;
		if (!vis[i])
			r[idx] = i;
	}
	for (int i = 1; i <= n; ++i)
		cin >> w[i], sum1[i] = sum1[i - 1] + w[i];
	for (int i = 0; i <= n; ++i)
	{
		for (int j = 1; j <= idx; ++j)
			f[i][j] = oo;
	}
	for (int i = 0; i <= n; ++i)
		f[i][0] = sum1[i];
	for (int j = 1; j <= idx; ++j)
	{
		if (vis[l[j]] & 1)
			app[t[l[j]] - 'a' + 1] = true;
		tot = 0;
		for (int k = 1; k <= n; ++k)
		{
			if (app[s[k] - 'a' + 1])
				ns[++tot] = s[k], id[tot] = k, sum2[tot] = sum2[tot - 1] + w[k];
		}
		id[0] = id[1] - 1;
		int p = l[j] - 1;
		for (int i = l[j] - 1; i <= r[j]; ++i)
			nxt[i] = l[j] - 1;
		for (int i = l[j] + 1; i <= r[j]; ++i)
		{
			while (p != l[j] - 1 && t[p + 1] != t[i])
				p = nxt[p];
			if (t[p + 1] == t[i])
				p++;
			nxt[i] = p;
		}
		p = l[j] - 1;
		int len = r[j] - l[j] + 1;
		for (int i = 1; i <= tot; ++i)
		{
			while (p != l[j] - 1 && t[p + 1] != ns[i])
				p = nxt[p];
			if (t[p + 1] == ns[i])
				p++;
			if (p == r[j])
			{
				f[id[i]][j] = std::min(f[id[i]][j], f[id[i - len + 1] - 1][j - 1] + sum1[id[i]] - sum1[id[i - len + 1] - 1] - (sum2[i] - sum2[i - len]));
				p = nxt[p];
			}
		}
		if (vis[r[j]] & 2)
			app[t[r[j]] - 'a' + 1] = false;
		for (int i = 1; i <= n; ++i)
		{
			if (!app[s[i] - 'a' + 1])
				f[i][j] = std::min(f[i][j], f[i - 1][j] + w[i]);
		}
	}
	ll ans = oo;
	for (int i = 1; i <= n; ++i)
		ans = std::min(ans, f[i][idx] + sum1[n] - sum1[i]);
	if (ans < oo)
		cout << ans << '\n';
	else
		cout << "You better start from scratch man..." << '\n';
	return 0;
}

7.AC 自动机(简单版)

点击查看代码
#include <iostream>
#include <string>
#include <queue>

using std::cin;
using std::cout;
const int N = 1e6 + 10;

int tot;
int word[N];
int fail[N];
int son[N][30];

void insert(std::string s)
{
	int now = 0;
	for (auto it : s)
	{
		int num = it - 'a' + 1;
		now = (son[now][num] ? son[now][num] : son[now][num] = ++tot);
	}
	word[now]++;
}
void build()
{
	std::queue<int> q;
	for (int i = 1; i <= 26; ++i)
	{
		if (son[0][i])
			q.push(son[0][i]);
	}
	while (q.size())
	{
		int now = q.front();
		q.pop();
		for (int i = 1; i <= 26; ++i)
		{
			if (son[now][i])
			{
				fail[son[now][i]] = son[fail[now]][i];
				q.push(son[now][i]);
			}
			else
				son[now][i] = son[fail[now]][i];
		}
	}
}
int query(std::string s)
{
	int ans = 0;
	int now = 0;
	for (auto it : s)
	{
		int num = it - 'a' + 1;
		now = son[now][num];
		for (int t = now; word[t] != -1; t = fail[t])
		{
			ans += word[t];
			word[t] = -1;
		}
	}
	return ans;
}

int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; ++i)
	{
		std::string s;
		cin >> s;
		insert(s);
	}
	build();
	std::string t;
	cin >> t;
	cout << query(t) << '\n';
	return 0;
}

8.AC 自动机(简单版 II)

点击查看代码
#include <iostream>
#include <string>
#include <queue>
#include <cstring>

using std::cin;
using std::cout;
const int N = 1e6 + 10;

int tot;
int cnt[N];
int word[N];
int fail[N];
int son[(int)1e5 + 10][30];
std::string s[N];

void insert(std::string s, int id)
{
	int now = 0;
	for (auto it : s)
	{
		int num = it - 'a' + 1;
		now = (son[now][num] ? son[now][num] : son[now][num] = ++tot);
	}
	word[now] = id;
}
void build()
{
	std::queue<int> q;
	for (int i = 1; i <= 26; ++i)
	{
		if (son[0][i])
			q.push(son[0][i]);
	}
	while (q.size())
	{
		int now = q.front();
		q.pop();
		for (int i = 1; i <= 26; ++i)
		{
			if (son[now][i])
			{
				fail[son[now][i]] = son[fail[now]][i];
				q.push(son[now][i]);
			}
			else
				son[now][i] = son[fail[now]][i];
		}
	}
}
void query(std::string s)
{
	int now = 0;
	for (auto it : s)
	{
		int num = it - 'a' + 1;
		now = son[now][num];
		for (int t = now; t; t = fail[t])
			cnt[word[t]]++;
	}
}

int main()
{
	int n;
	while (cin >> n)
	{
		if (n == 0)
			break;
		tot = 0;
		memset(cnt, 0, sizeof(cnt));
		memset(word, 0, sizeof(word));
		memset(son, 0, sizeof(son));
		memset(fail, 0, sizeof(fail));
		for (int i = 1; i <= n; ++i)
		{
			cin >> s[i];
			insert(s[i], i);
		}
		build();
		std::string p;
		cin >> p;
		query(p);
		int mx = 0;
		for (int i = 1; i <= n; ++i)
			mx = std::max(mx, cnt[i]);
		cout << mx << '\n';
		for (int i = 1; i <= n; ++i)
		{
			if (mx == cnt[i])
				cout << s[i] << '\n';
		}
	}
	return 0;
}

9.AC 自动机

点击查看代码
#include <iostream>
#include <string>
#include <vector>
#include <queue>

using std::cin;
using std::cout;
const int N = 2e5 + 10;
const int M = 2e6 + 10;

int tot;
int p[N];
int sum[N];
int fail[N];
int son[N][30];
std::vector<int> to[N];

void insert(std::string s, int id)
{
	int now = 0;
	for (auto it : s)
	{
		int num = it - 'a' + 1;
		now = (son[now][num] ? son[now][num] : son[now][num] = ++tot);
	}
	p[id] = now;
}
void build()
{
	std::queue<int> q;
	for (int i = 1; i <= 26; ++i)
	{
		if (son[0][i])
			q.push(son[0][i]), fail[son[0][i]] = 0;
	}
	while (q.size())
	{
		int now = q.front();
		q.pop();
		for (int i = 1; i <= 26; ++i)
		{
			if (son[now][i])
			{
				q.push(son[now][i]);
				fail[son[now][i]] = son[fail[now]][i];
			}
			else
				son[now][i] = son[fail[now]][i];
		}
	}
	for (int i = 1; i <= tot; ++i)
		to[fail[i]].push_back(i);
}
void get(std::string t)
{
	int now = 0;
	for (auto it : t)
	{
		int num = it - 'a' + 1;
		now = son[now][num];
		sum[now]++;
	}
}
void calc(int x)
{
	for (auto it : to[x])
		calc(it);
	for (auto it : to[x])
		sum[x] += sum[it];
}

int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; ++i)
	{
		std::string t;
		cin >> t;
		insert(t, i);
	}
	build();
	std::string s;
	cin >> s;
	get(s);
	calc(0);
	for (int i = 1; i <= n; ++i)
		cout << sum[p[i]] << '\n';
	return 0;
}

10.病毒

点击查看代码
#include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <cstdlib>

using std::cin;
using std::cout;
const int N = 3e4 + 10;

int tot;
std::string s;
bool is[N];
bool vs[N];
bool vis[N];
int fail[N];
int son[N][2];
std::vector<int> e[N];

void ins()
{
	int now = 0;
	for (char c : s)
	{
		int k = c - '0';
		if (!son[now][k])
			son[now][k] = ++tot;
		now = son[now][k];
	}
	is[now] = true;
}
void build()
{
	std::queue<int> q;
	for (int i = 0; i <= 1; ++i)
	{
		if (son[0][i])
		{
			e[0].push_back(son[0][i]);
			q.push(son[0][i]);
		}
	}
	while (q.size())
	{
		int x = q.front();
		q.pop();
		for (int i = 0; i <= 1; ++i)
		{
			if (son[x][i])
			{
				fail[son[x][i]] = son[fail[x]][i];
				q.push(son[x][i]);
				e[fail[son[x][i]]].push_back(son[x][i]);
			}
			else
				son[x][i] = son[fail[x]][i];
		}
	}
}
void tag(int x)
{
	for (auto to : e[x])
	{
		is[to] |= is[x];
		tag(to);
	}
}
void dfs(int x)
{
	vis[x] = true;
	vs[x] = true;
	for (int i = 0; i <= 1; ++i)
	{
		if (!is[son[x][i]] && !vs[son[x][i]])
			dfs(son[x][i]);
		else if (vis[son[x][i]])
		{
			cout << "TAK" << '\n';
			exit(0);
		}	
	}
	vis[x] = false;
}

int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; ++i)
	{
		cin >> s;
		ins();
	}
	build();
	tag(0);
	dfs(0);
	cout << "NIE" << '\n';
	return 0;
}

ps:dfs判环要开两个bool数组,一个表示访没访问过,一个表示在不在这条路径上。

11.阿狸的打字机

点击查看代码
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
#define lowbit(x) x & (-x)

using std::cin;
using std::cout;
const int N = 1e5 + 10;
struct Q
{
	int id, x;
};

int cn;
int idx;
int tot;
char c[N];
int p[N];
int fa[N];
int ans[N];
int dfn[N];
int siz[N];
int sum[N];
int fail[N];
std::queue<int> q;
std::vector<Q> qr[N];
int s[N][27];
int son[N][27];
std::vector<int> e[N];

void add(int x, int k)
{
	for (; x <= idx; x += lowbit(x))
		sum[x] += k;
}
int qu(int x)
{
	int ret = 0;
	for (; x; x -= lowbit(x))
		ret += sum[x];
	return ret;
}
void build()
{
	for (int i = 1; i <= 26; ++i)
	{
		if (son[0][i])
		{
			q.push(son[0][i]);
			e[0].push_back(son[0][i]);
		}
	}
	while (q.size())
	{
		int x = q.front();
		q.pop();
		for (int i = 1; i <= 26; ++i)
		{
			if (son[x][i])
			{
				fail[son[x][i]] = son[fail[x]][i];
				e[fail[son[x][i]]].push_back(son[x][i]);
				q.push(son[x][i]);
			}
			else
				son[x][i] = son[fail[x]][i];
		}
	}
}
void dfs(int x)
{
	siz[x] = 1;
	dfn[x] = ++idx;
	for (auto to : e[x])
	{
		dfs(to);
		siz[x] += siz[to];
	}
}
void dfs1(int x)
{
	add(dfn[x], 1);
	for (auto it : qr[x])
	{
		int id = it.id;
		int xx = it.x;
		ans[id] = qu(dfn[xx] + siz[xx] - 1) - qu(dfn[xx] - 1);
	}
	for (int i = 1; i <= 26; ++i)
	{
		if (s[x][i])
			dfs1(s[x][i]);
	}
	add(dfn[x], -1);
}

int main()
{
	cin >> (c + 1);
	int n = strlen(c + 1);
	int now = 0;
	for (int i = 1; i <= n; ++i)
	{
		if (c[i] == 'B')
			now = fa[now];
		else if (c[i] == 'P')
			p[++cn] = now;
		else
		{
			if (!son[now][c[i] - 'a' + 1])
				son[now][c[i] - 'a' + 1] = ++tot, s[now][c[i] - 'a' + 1] = tot, fa[tot] = now;
			now = son[now][c[i] - 'a' + 1];
		}
	}
	build();
	dfs(0);
	int m;
	cin >> m;
	for (int i = 1; i <= m; ++i)
	{
		int x, y;
		cin >> x >> y;
		qr[p[y]].push_back({i, p[x]});
	}
	dfs1(0);
	for (int i = 1; i <= m; ++i)
		cout << ans[i] << '\n';
	return 0;
}

12.Exam

点击查看代码
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#define lowbit(x) x & (-x)

using std::cin;
using std::cout;
const int N = 1e6 + 10;
struct Q
{
	int cn, x, deb1, deb2;
};

bool vis[N];
bool ps[N];
int idx;
int ans;
int tot;
int p[N];
int mx[N];
int nr[N];
int pre[N];
int dfn[N];
int siz[N];
int cnt[N];
int sum[N];
int fail[N];
int sn[N][27];
int son[N][27];
std::vector<int> app;
std::string s[N];
std::vector<int> e[N];
std::vector<Q> qr[N];
std::vector<int> Id[N];

void add(int x, int k)
{
	for (; x <= idx; x += lowbit(x))
		sum[x] += k;
}
int qu(int x)
{
	int ret = 0;
	for (; x; x -= lowbit(x))
		ret += sum[x];
	return ret;
}
void ins(int id, std::string s)
{
	int now = 0;
	for (auto c : s)
	{
		int k = c - 'a' + 1;
		if (!son[now][k])
			sn[now][k] = son[now][k] = ++tot;
		now = son[now][k];
	}
	p[id] = now;
	Id[now].push_back(id);
}
void build()
{
	std::queue<int> q;
	for (int i = 1; i <= 26; ++i)
	{
		if (son[0][i])
		{
			q.push(son[0][i]);
			e[0].push_back(son[0][i]);
		}
	}
	while (q.size())
	{
		int x = q.front();
		q.pop();
		for (int i = 1; i <= 26; ++i)
		{
			if (son[x][i])
			{
				fail[son[x][i]] = son[fail[x]][i];
				q.push(son[x][i]);
				e[fail[son[x][i]]].push_back(son[x][i]);
			}
			else
				son[x][i] = son[fail[x]][i];
		}
	}
}
void dfs(int x, int now)
{
	if (Id[x].size() >= 3)
	{
		for (auto i : Id[x])
			vis[i] = true;
		for (auto to : e[x])
			dfs(to, Id[x][0]);
	}
	else if (Id[x].size() == 2)
	{
		vis[Id[x][0]] = vis[Id[x][1]] = true;
		ans++;
		for (auto to : e[x])
			dfs(to, Id[x][0]);
	}
	else
	{
		pre[x] = now;
		if (Id[x].size())
			now = Id[x][0];
		nr[x] = now;
		for (auto to : e[x])
			dfs(to, now);
	}
}
void dfs1(int x)
{
	dfn[x] = ++idx;
	siz[x] = 1;
	for (auto to : e[x])
	{
		dfs1(to);
		siz[x] += siz[to];
	}
}
void dfs2(int x)
{
	add(dfn[x], 1);
	for (auto now : qr[x])
	{
		int xx = now.x;
		ans += (now.cn == qu(dfn[xx] + siz[xx] - 1) - qu(dfn[xx] - 1));
	}
	for (int i = 1; i <= 26; ++i)
	{
		int s = sn[x][i];
		if (s)
			dfs2(s);
	}
	add(dfn[x], -1);
}

int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; ++i)
	{
		cin >> s[i];
		ins(i, s[i]);
	}
	build();
	dfs(0, 0);
	dfs1(0);
	for (int i = 1; i <= n; ++i)
	{
		if (vis[i])
			continue;
		int now = 0;
		app.clear();
		for (int j = 0; j < s[i].size(); ++j)
		{
			now = son[now][s[i][j] - 'a' + 1];
			mx[j] = (j == s[i].size() - 1 ? pre[now] : nr[now]);
			if (mx[j] && !vis[mx[j]] && !ps[mx[j]])
				app.push_back(mx[j]), ps[mx[j]] = true, cnt[mx[j]] = 0;
		}
		int nl = 1e9;
		for (int j = s[i].size() - 1; j >= 0; --j)
		{
			if (mx[j] && !vis[mx[j]] && j - s[mx[j]].size() + 1 < nl)
			{
				cnt[mx[j]]++;
				nl = j - s[mx[j]].size() + 1;
			}
		}
		for (auto j : app)
		{
			ps[j] = false;
			if (cnt[j])
				qr[p[i]].push_back({cnt[j], p[j], i, j});
		}
	}
	dfs2(0);
	cout << ans << '\n';
	return 0;
}

ps:一定要处理好多个串相同的情况。

13.Video Game G

点击查看代码
#include <iostream>
#include <queue>
#include <vector>

using std::cin;
using std::cout;
const int N = 300 + 10;
const int M = 1e3 + 10;
const int oo = 1e9 + 10;

int tot;
int cnt[N];
int fail[N];
int son[N][4];
int f[M][N];
std::string s;
std::vector<int> e[N];

void ins()
{
	int now = 0;
	for (auto c : s)
	{
		int k = c - 'A' + 1;
		if (!son[now][k])
			son[now][k] = ++tot;
		now = son[now][k];
	}
	cnt[now]++;
}
void build()
{
	std::queue<int> q;
	for (int i = 1; i <= 3; ++i)
	{
		if (son[0][i])
		{
			q.push(son[0][i]);
			e[0].push_back(son[0][i]);
		}
	}
	while (q.size())
	{
		int x = q.front();
		q.pop();
		for (int i = 1; i <= 3; ++i)
		{
			if (son[x][i])
			{
				fail[son[x][i]] = son[fail[x]][i];
				q.push(son[x][i]);
				e[fail[son[x][i]]].push_back(son[x][i]);
			}
			else
				son[x][i] = son[fail[x]][i];
		}
	}
}
void dfs(int x)
{
	for (auto to : e[x])
	{
		cnt[to] += cnt[x];
		dfs(to);
	}
}

int main()
{
	int n, k;
	cin >> n >> k;
	for (int i = 1; i <= n; ++i)
	{
		cin >> s;
		ins();
	}
	build();
	dfs(0);
	for (int i = 0; i <= k; ++i)
	{
		for (int j = 0; j <= tot; ++j)
			f[i][j] = -oo;
	}
	f[0][0] = 0;
	for (int i = 1; i <= k; ++i)
	{
		for (int j = 0; j <= tot; ++j)
		{
			for (int l = 1; l <= 3; ++l)
				f[i][son[j][l]] = std::max(f[i][son[j][l]], f[i - 1][j] + cnt[son[j][l]]);
		}
	}
	int ans = -oo;
	for (int i = 0; i <= tot; ++i)
		ans = std::max(ans, f[k][i]);
	cout << ans << '\n';
	return 0;
}

14.禁忌

点击查看代码
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <vector>

using std::cin;
using std::cout;
const int N = 80;
typedef long double ld;
struct Mat
{
	int n, m;
	ld a[N][N];
	Mat()
	{
		memset(a, 0, sizeof(a));
	}
	void init(int x)
	{
		Mat();
		n = m = x;
		for (int i = 0; i <= x; ++i)
			a[x][x] = 1;
	}
	friend Mat operator*(const Mat &a, const Mat &b)
	{
		Mat ret;
		ret.n = a.n;
		ret.m = b.m;
		for (int i = 0; i <= a.n; ++i)
		{
			for (int j = 0; j <= a.m; ++j)
			{
				for (int k = 0; k <= b.m; ++k)
					ret.a[i][k] += a.a[i][j] * b.a[j][k];
			}
		}
		return ret;
	}
} k, st;

int tot;
int n, len, al;
bool is[N];
int fail[N];
int son[N][27];
std::vector<int> e[N];

void ins(std::string s)
{
	int now = 0;
	for (auto c : s)
	{
		int k = c - 'a' + 1;
		if (!son[now][k])
			son[now][k] = ++tot;
		now = son[now][k];
	}
	is[now] = true;
}
void build()
{
	std::queue<int> q;
	for (int i = 1; i <= al; ++i)
	{
		if (son[0][i])
			q.push(son[0][i]), e[0].push_back(son[0][i]);
	}
	while (q.size())
	{
		int x = q.front();
		q.pop();
		for (int i = 1; i <= al; ++i)
		{
			if (son[x][i])
			{
				fail[son[x][i]] = son[fail[x]][i];
				e[fail[son[x][i]]].push_back(son[x][i]);
				q.push(son[x][i]);
			}
			else
				son[x][i] = son[fail[x]][i];
		}
	}
}
Mat ksm(Mat a, int b)
{
	Mat ret;
	ret.init(a.n);
	for (; b; a = a * a, b >>= 1)
	{
		if (b & 1)
			ret = ret * a;
	}
	return ret;
}
void dfs(int x)
{
	for (auto to : e[x])
	{
		is[to] |= is[x];
		dfs(to);
	}
}

int main()
{
	cin >> n >> len >> al;
	for (int i = 1; i <= n; ++i)
	{
		std::string s;
		cin >> s;
		ins(s);
	}
	build();
	dfs(0);
	k.n = k.m = tot + 1;
	for (int i = 0; i <= tot; ++i)
	{
		for (int j = 1; j <= al; ++j)
		{
			if (is[son[i][j]])
			{
				k.a[tot + 1][i] += (ld)1 / al;
				k.a[0][i] += (ld)1 / al;
			}
			else
				k.a[son[i][j]][i] += (ld)1 / al;
		}
	}
	k.a[tot + 1][tot + 1] = 1;
	st.n = tot + 1, st.m = 0, st.a[0][0] = 1;
	st = ksm(k, len) * st;
	printf("%.7Lf\n", st.a[tot + 1][0]);
	return 0;
}
posted @ 2026-08-14 08:23  SigmaToT  阅读(8)  评论(0)    收藏  举报