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;
        }
    }
}
posted @ 2021-07-29 22:02  naymi  阅读(31)  评论(0)    收藏  举报