day-17
字典树
https://vjudge.net/problem/UVALive-3942/origin
字典树维护dp转移 记忆化搜索.
const int maxn = 2e6 + 7;
const int mod = 20071027;
int n, t, m;
int dp[maxn], nex[maxn][26], cnt, vis[maxn];
char s[maxn];
void insert(char *s) {
int l = strlen(s), p = 0;
for (int i = 0, c; i < l; i++) {
c = s[i] - 'a';
if (!nex[p][c]) nex[p][c] = ++cnt;
p = nex[p][c];
}
vis[p]++;
}
ll find(char *s, int pl) {
if (pl == n)
return 1;
if (dp[pl] != -1)
return dp[pl];
int p = 0, res = 0;
for (int i = pl; i < n; i++) {
int c = s[i] - 'a';
if (!nex[p][c]) break;
p = nex[p][c];
if (vis[p]) {
res += find(s, i + 1);
res %= mod;
}
}
dp[pl] = res % mod;
return res % mod;
}
void solve() {
int id = 1;
while (scanf("%s", s) != EOF) {
memset(dp, -1, sizeof dp);
memset(nex, 0, sizeof nex);
memset(vis, 0, sizeof vis);
n = strlen(s);
scanf("%d", &t);
char ss[101];
for (int i = 1; i <= t; i++) {
// cin >> ss;
scanf("%s", ss);
insert(ss);
}
cout << "Case " << id++ << ": " << find(s, 0) << endl;
}
}
https://codeforces.com/contest/858/problem/D
撤销影响
const int maxn = 2e6 + 7;
int n, t, m;
int nex[maxn][12], vis[maxn], cnt;
void insert(char *s) {
int l = strlen(s), p = 0;
for (int i = 0, c; i < l; i++) {
c = s[i] - '0';
if (!nex[p][c]) nex[p][c] = ++cnt;
p = nex[p][c];
vis[p]++;
}
}
void del(char *s) {
int l = strlen(s), p = 0;
for (int i = 0, c; i < l; i++) {
c = s[i] - '0';
p = nex[p][c];
vis[p]--;
}
}
string ans;
void find(char *s) {
string res;
int l = strlen(s), p = 0, fg = 0;
for (int i = 0, c; i < l; i++) {
c = s[i] - '0';
res += s[i];
p = nex[p][c];
if (vis[p] == 0) {
fg = 1;
break;
}
}
if (fg && ans.size() > res.size())
ans = res;
}
char s[maxn][12];
void solve() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> s[i];
for (int j = 0; j < 9; j++)
insert(s[i] + j);
}
for (int i = 1; i <= n; i++) {
for (int j = 0; j < 9; j++)
del(s[i] + j);
ans = "99999999999999";
for (int st = 0; st < 9; st++) {
find(s[i] + st);
}
cout << ans << endl;
for (int j = 0; j < 9; j++)
insert(s[i] + j);
}
}
01字典树
https://www.luogu.com.cn/problem/P4551
树上路径(u,v)的异或 equ to (root,u) ^ (root,v)
const int maxn = 1e6 + 7;
int n, t, m;
int nex[maxn][3], cnt;
vector<int> vec;
void insert(int x) {
vec.push_back(x);
int p = 0;
for (int i = 30; i >= 0; i--) {
if (!nex[p][(x >> i) & 1]) nex[p][(x >> i) & 1] = ++cnt;
p = nex[p][(x >> i) & 1];
}
}
struct edg {
int u, w;
};
vector<edg> mp[maxn];
void dfs(int u, int f, int x) {
// if (f)
insert(x);
for (auto e:mp[u]) {
if (e.u == f)
continue;
dfs(e.u, u, e.w ^ x);
}
}
int find(int x) {
int ans = 0, p = 0;
for (int i = 30; i >= 0; i--) {
if ((x >> i) & 1) {
if (nex[p][0])
ans |= (1 << i), p = nex[p][0];
else
p = nex[p][1];
} else {
if (nex[p][1])
ans |= (1 << i), p = nex[p][1];
else
p = nex[p][0];
}
}
return ans;
}
void solve() {
cin >> n;
for (int i = 1, u, v, w; i < n; i++) {
cin >> u >> v >> w;
mp[u].push_back({v, w});
mp[v].push_back({u, w});
}
dfs(1, 0, 0);
int mi = 0;
for (auto i:vec)
mi = max(mi, find(i));
cout << mi << endl;
}
https://codeforces.com/problemset/problem/979/D
建立k颗字典树 对每个节点维护可以访问的x的最小值
const int maxn = 1e5 + 7;
int n, t, m;
int nex[maxn * 400][2], vis[maxn * 400], cnt = maxn;
vector<int> vec[maxn];
void init() {
for (int i = 1; i < maxn; i++)
for (int j = i; j < maxn; j += i)
vec[j].push_back(i);
memset(vis, 0x3f, sizeof vis);
}
void insert(int k, int x) {
int p = k;
for (int i = 19; i >= 0; i--) {
int c = x >> i & 1;
if (!nex[p][c]) nex[p][c] = ++cnt;
p = nex[p][c];
vis[p] = min(vis[p], x);
}
}
int query(int x, int k, int s) {
if (x % k) return -1;
int p = k;
for (int i = 19; i >= 0; i--) {
int c = (x >> i) & 1;
if (nex[p][!c] && (vis[nex[p][!c]] + x <= s)) p = nex[p][!c];
else p = nex[p][c];
}
if (vis[p] + x > s)return -1;
return vis[p];
}
void solve() {
init();
cin >> t;
while (t--) {
int op, a, b, c;
cin >> op;
if (op == 1) {
cin >> a;
for (auto i:vec[a]) insert(i, a);
} else {
cin >> a >> b >> c;
cout << query(a, b, c) << endl;
}
}
}
我看见 你