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;
}

浙公网安备 33010602011771号