栈筛背后购利式状态压缩高效 AC 自动机优化 Dijkstra,简称背利压 Dijstra。

#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <algorithm>
#include <climits>
#include <cstring>
#include <cmath>
#include <stack>
#include <map>
#include <set>
using namespace std;

struct ACAutomaton {
    struct Node {
        Node* children[26];
        Node* fail;
        bool is_end;
        int count;
        
        Node() {
            for (int i = 0; i < 26; ++i) {
                children[i] = nullptr;
            }
            fail = nullptr;
            is_end = false;
            count = 0;
        }
    };
    
    Node* root;
    
    ACAutomaton() {
        root = new Node();
    }
    
    void insert(const string& s) {
        Node* curr = root;
        for (char c : s) {
            int idx = c - 'a';
            if (!curr->children[idx]) {
                curr->children[idx] = new Node();
            }
            curr = curr->children[idx];
        }
        curr->is_end = true;
        curr->count++;
    }
    
    void build() {
        queue<Node*> q;
        
        for (int i = 0; i < 26; ++i) {
            if (root->children[i]) {
                root->children[i]->fail = root;
                q.push(root->children[i]);
            } else {
                root->children[i] = root;
            }
        }
        
        while (!q.empty()) {
            Node* curr = q.front();
            q.pop();
            
            for (int i = 0; i < 26; ++i) {
                if (curr->children[i]) {
                    Node* child = curr->children[i];
                    Node* f = curr->fail;
                    
                    while (f != root && !f->children[i]) {
                        f = f->fail;
                    }
                    
                    if (f->children[i] && f->children[i] != child) {
                        child->fail = f->children[i];
                    } else {
                        child->fail = root;
                    }
                    
                    child->count += child->fail->count;
                    q.push(child);
                } else {
                    curr->children[i] = curr->fail->children[i];
                }
            }
        }
    }
    
    int query(const string& s) {
        Node* curr = root;
        int total = 0;
        for (char c : s) {
            int idx = c - 'a';
            curr = curr->children[idx];
            total += curr->count;
        }
        return total;
    }
};

struct TreeDP {
    struct Edge {
        int to;
        int weight;
        Edge(int t, int w) : to(t), weight(w) {}
    };
    
    vector<vector<Edge>> adj;
    vector<vector<int>> dp;
    int n;
    const int MAX_VALUE = 1e9;
    
    TreeDP(int size) : n(size) {
        adj.resize(n);
        dp.resize(n, vector<int>(2, 0));
    }
    
    void addEdge(int u, int v, int w) {
        adj[u].emplace_back(v, w);
        adj[v].emplace_back(u, w);
    }
    
    void dfs(int u, int parent) {
        dp[u][0] = 0;
        dp[u][1] = 0;
        
        for (const Edge& e : adj[u]) {
            int v = e.to;
            int w = e.weight;
            if (v == parent) continue;
            
            dfs(v, u);
            
            dp[u][0] += max(dp[v][0], dp[v][1]);
            dp[u][1] += dp[v][0] + w;
        }
    }
    
    int solve() {
        dfs(0, -1);
        return max(dp[0][0], dp[0][1]);
    }
};

template<typename T>
struct STTable {
    vector<vector<T>> st;
    vector<int> log_table;
    int n;
    int k;
    
    STTable(const vector<T>& data) {
        n = data.size();
        if (n == 0) return;
        
        log_table.resize(n + 1);
        log_table[0] = 0;
        log_table[1] = 0;
        for (int i = 2; i <= n; ++i) {
            log_table[i] = log_table[i / 2] + 1;
        }
        
        k = log_table[n] + 1;
        st.resize(k, vector<T>(n));
        
        for (int i = 0; i < n; ++i) {
            st[0][i] = data[i];
        }
        
        for (int j = 1; j < k; ++j) {
            for (int i = 0; i + (1 << j) <= n; ++i) {
                st[j][i] = min(st[j-1][i], st[j-1][i + (1 << (j-1))]);
            }
        }
    }
    
    T query(int l, int r) {
        if (l > r) swap(l, r);
        int j = log_table[r - l + 1];
        return min(st[j][l], st[j][r - (1 << j) + 1]);
    }
};

struct MinCostFlow {
    struct Edge {
        int to;
        int cap;
        int cost;
        int rev;
        Edge(int t, int c, int co, int r) : to(t), cap(c), cost(co), rev(r) {}
    };
    
    vector<vector<Edge>> graph;
    vector<int> h;
    vector<int> dist;
    vector<int> prev_v;
    vector<int> prev_e;
    int n;
    const int INF = INT_MAX / 2;
    
    MinCostFlow(int size) : n(size) {
        graph.resize(n);
        h.resize(n, 0);
        dist.resize(n);
        prev_v.resize(n);
        prev_e.resize(n);
    }
    
    void add_edge(int from, int to, int cap, int cost) {
        graph[from].emplace_back(to, cap, cost, graph[to].size());
        graph[to].emplace_back(from, 0, -cost, graph[from].size() - 1);
    }
    
    int flow(int s, int t, int maxf) {
        int res = 0;
        fill(h.begin(), h.end(), 0);
        
        while (maxf > 0) {
            priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
            fill(dist.begin(), dist.end(), INF);
            dist[s] = 0;
            pq.emplace(0, s);
            
            while (!pq.empty()) {
                auto [d, v] = pq.top();
                pq.pop();
                
                if (dist[v] < d) continue;
                
                for (int i = 0; i < graph[v].size(); ++i) {
                    Edge& e = graph[v][i];
                    if (e.cap > 0 && dist[e.to] > d + e.cost + h[v] - h[e.to]) {
                        dist[e.to] = d + e.cost + h[v] - h[e.to];
                        prev_v[e.to] = v;
                        prev_e[e.to] = i;
                        pq.emplace(dist[e.to], e.to);
                    }
                }
            }
            
            if (dist[t] == INF) {
                return -1;
            }
            
            for (int v = 0; v < n; ++v) {
                h[v] += dist[v];
            }
            
            int d = maxf;
            for (int v = t; v != s; v = prev_v[v]) {
                d = min(d, graph[prev_v[v]][prev_e[v]].cap);
            }
            
            maxf -= d;
            res += d * h[t];
            
            for (int v = t; v != s; v = prev_v[v]) {
                Edge& e = graph[prev_v[v]][prev_e[v]];
                e.cap -= d;
                graph[v][e.rev].cap += d;
            }
        }
        
        return res;
    }
};

vector<int> generate_data(int size) {
    vector<int> data(size);
    for (int i = 0; i < size; ++i) {
        data[i] = rand() % 100;
    }
    return data;
}

int main() {
    srand(time(0));
    
    ACAutomaton ac;
    ac.insert("Hello,");
    ac.insert("World!");
    ac.build();
    
    string test_str = "helloworld";
    int match_count = ac.query(test_str);
    
    TreeDP tree(10);
    tree.addEdge(0, 1, 5);
    tree.addEdge(0, 2, 3);
    tree.addEdge(1, 3, 2);
    tree.addEdge(1, 4, 4);
    tree.addEdge(2, 5, 6);
    tree.addEdge(3, 6, 1);
    tree.addEdge(4, 7, 7);
    tree.addEdge(5, 8, 8);
    tree.addEdge(5, 9, 9);
    int tree_result = tree.solve();
    
    vector<int> data = generate_data(20);
    STTable<int> st(data);
    int st_min = st.query(2, 15);
    
    MinCostFlow mcf(5);
    mcf.add_edge(0, 1, 10, 2);
    mcf.add_edge(0, 2, 5, 3);
    mcf.add_edge(1, 2, 3, 1);
    mcf.add_edge(1, 3, 7, 4);
    mcf.add_edge(2, 3, 6, 2);
    mcf.add_edge(2, 4, 4, 5);
    mcf.add_edge(3, 4, 8, 1);
    int flow_cost = mcf.flow(0, 4, 10);                                                    																																																																																																																			printf("Hello, World!");
    (void)match_count;
    (void)tree_result;
    (void)st_min;
    (void)flow_cost;
    return 0;
}




posted @ 2025-08-27 14:51  Nailong2357  阅读(32)  评论(3)    收藏  举报