AC 自动机

struct Trie {
    int ch[N][2];
    int end[N];
    int fail[N];
    int sz;
    int root;
    int mark[M];
    int new_node() {
        ch[sz][0] = ch[sz][1] = -1;
        end[sz] = 0;
        return sz ++;
    }
    void init() {
        sz = 0;
        root = new_node();
    }
    void insert(char *s, int f) {
        int len = strlen(s);
        int now = root;
        for (int i = 0; i < len; i++) {
            int etr = s[i] - '0';
            if (ch[now][etr] == -1)
                ch[now][etr] = new_node();
            now = ch[now][etr];
        }
        end[now] = f;
        if (f != -1) 
            mark[f] = now;
    }
    queue<int> que;
    void build() {
        while (!que.empty()) 
            que.pop();
        fail[root] = root;
        for (int k = 0; k < 2; k++) 
            if (ch[root][k] == -1) 
                ch[root][k] = root;
            else {
                fail[ch[root][k]] = root;
                que.push(ch[root][k]);
            }
        while (!que.empty()) {
            int v = que.front(); que.pop();
            for (int k = 0; k < 2; k++) {
                if (ch[v][k] == -1) 
                    ch[v][k] = ch[fail[v]][k];
                else {
                    fail[ch[v][k]] = ch[fail[v]][k];
                    que.push(ch[v][k]);
                }
            }
        }
    }
    void debug() {
        for (int i = 0; i < sz; i++) {
            printf("id = %3d, fail = %3d, end = %3d, chi = [", i, fail[i], end[i]);
            for (int j = 0; j < 2; j++) 
                printf("%4d", ch[i][j]);
            printf("]\n");
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                printf("%d ", path[i][j]);
            }
            puts("");
        }
    }
} t;

Problem

http://acm.hdu.edu.cn/showproblem.php?pid=3247

构造AC自动机,建立每个串尾到其它串尾的距离,然后状压出最小距离。

# include <bits/stdc++.h>
using namespace std;
# define X first
# define Y second
# define sq(x) ((x)*(x))
# define Mem(x,y) memset(x,y,sizeof(x))
# define cMin(x,y) ((x)=((x)<(y)?(x):(y)))
# define cMax(x,y) ((x)=((x)>(y)?(x):(y)))
# define In(x1,y1,x2,y2) ((x2)<=(x1)&&(y1)<=(y2))
# define Dv(x1,y1,x2,y2) ((y1)<(x2)||(y2)<(x1))
# define show(x) cerr << #x << " = " << x << endl
# define time cerr<<"\n\n"<<"Time Spec = "<<clock()/1000.<<"s\n"
typedef double DB;
typedef long long LL;
typedef pair<int, int> Pr;
typedef unsigned long long U;
const LL INF = 1e9 + 100;
const DB EPS = 1e-8;
const int N = 6e4 + 100;
const int M = 12;
const int L = 1e5 + 100;
const int MOD = 998244353;
int n, m;
struct Trie {
    int ch[N][2];
    int end[N];
    int fail[N];
    int sz;
    int root;
    int mark[M];
    int new_node() {
        ch[sz][0] = ch[sz][1] = -1;
        end[sz] = 0;
        return sz ++;
    }
    void init() {
        sz = 0;
        root = new_node();
    }
    void insert(char *s, int f) {
        int len = strlen(s);
        int now = root;
        for (int i = 0; i < len; i++) {
            int etr = s[i] - '0';
            if (ch[now][etr] == -1)
                ch[now][etr] = new_node();
            now = ch[now][etr];
        }
        end[now] = f;
        if (f != -1) 
            mark[f] = now;
    }
    queue<int> que;
    void build() {
        while (!que.empty()) 
            que.pop();
        fail[root] = root;
        for (int k = 0; k < 2; k++) 
            if (ch[root][k] == -1) 
                ch[root][k] = root;
            else {
                fail[ch[root][k]] = root;
                que.push(ch[root][k]);
            }
        while (!que.empty()) {
            int v = que.front(); que.pop();
            for (int k = 0; k < 2; k++) {
                if (ch[v][k] == -1) 
                    ch[v][k] = ch[fail[v]][k];
                else {
                    fail[ch[v][k]] = ch[fail[v]][k];
                    que.push(ch[v][k]);
                }
            }
        }
        n = n + 1;
        mark[0] = 0;
        for (int i = 0; i <= n; i++) 
            bfs(i);
    }
    int path[M][M];
    int d[N];
    bool inque[N];
    void bfs(int s) {
        while (!que.empty()) 
            que.pop();
        for (int i = 0; i < sz; i++) 
            d[i] = INF, inque[i] = false;
        d[mark[s]] = 0;
        que.push(mark[s]);
        inque[mark[s]] = true;
        while (!que.empty()) {
            int v = que.front(); que.pop();
            for (int k = 0; k < 2; k++) {
                int u = ch[v][k];
                if (end[u] == -1) continue;
                if (d[u] > d[v] + 1) {
                    d[u] = d[v] + 1;
                    if (!inque[u]) 
                        que.push(u), inque[u] = true;
                }
            }
            // if (v != root) {
            //     if (d[fail[v]] > d[v]) {
            //         d[fail[v]] = d[v];
            //         if (!inque[fail[v]]) 
            //             que.push(fail[v]), inque[fail[v]] = true;
            //     }
            // }
            inque[v] = false;
        }
        for (int i = 0; i < n; i++) 
            path[s][i] = d[mark[i]];
    }
    int dp[1<<M][M];
    int get_ans() {
        for (int s = 0; s < (1 << n); s++) 
            for (int j = 0; j < n; j++) 
                dp[s][j] = INF;
        dp[1][0] = 0;
        for (int s = 0; s < (1 << n); s++) {
            for (int j = 0; j < n; j++) {
                for (int i = 0; i < n; i++) {
                    if ((s >> i) & 1) 
                        continue;
                    cMin(dp[s | (1 << i)][i], dp[s][j] + path[j][i]);
                }
            }
        }
        int ret = INF;
        int s = (1 << n) - 1;
        for (int i = 0; i < n; i++)
            cMin(ret, dp[s][i]);
        return ret;
    }
    void debug() {
        for (int i = 0; i < sz; i++) {
            printf("id = %3d, fail = %3d, end = %3d, chi = [", i, fail[i], end[i]);
            for (int j = 0; j < 2; j++) 
                printf("%4d", ch[i][j]);
            printf("]\n");
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                printf("%d ", path[i][j]);
            }
            puts("");
        }
    }
} t;
char s[L];
int main() {
# ifdef owly
    freopen("in.txt", "r", stdin);
    // freopen("ou.txt", "w", stdout);
# endif
    while (scanf("%d%d", &n, &m), n || m) {
        t.init();
        for (int i = 1; i <= n; i++) {
            scanf("%s", s);
            t.insert(s, i);
        }
        for (int i = 0; i < m; i++) {
            scanf("%s", s);
            t.insert(s, -1);
        }
        t.build();
        printf("%d\n", t.get_ans());
        // t.debug();
    }
    return 0;
}

results matching ""

    No results matching ""