AC自动机部分题目

模板题:

Keywords Search

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

typedef long long LL;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double inf = ~0u>>2;


using namespace std;

const int N = 10010;

struct Node {
    Node* fail;
    Node* next[26];
    int cnt;
    Node() {
        CL(next, NULL);
        fail = NULL;
        cnt = 0;
    }
};

class AC_automaton : public Node {
public:
    Node* root;
    int head, tail;

    void init() {root = new Node(); head = tail = 0;}

    void Insert(char* );
    void Build();
    int Search(char* );
}AC;

void AC_automaton::Insert(char* st) {
    Node* p = root;
    while(*st) {
        if(p->next[*st - 'a'] == NULL) {
            p->next[*st - 'a'] = new Node();
        }
        p = p->next[*st - 'a'];
        st++;
    }
    p->cnt++;
}

void AC_automaton::Build() {
    root->fail = NULL;
    deque<Node* > q;
    q.push_back(root);

    while(!q.empty()) {
        Node* tmp = q.front();
        Node* p = NULL;
        q.pop_front();

        for(int i = 0; i < 26; ++i) {
            if(tmp->next[i] != NULL) {
                if(tmp == root) tmp->next[i]->fail = root;
                else {
                    p = tmp->fail;
                    while(p != NULL) {
                        if(p->next[i] != NULL) {
                            tmp->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if(p == NULL)   tmp->next[i]->fail = root;
                }
                q.push_back(tmp->next[i]);
            }
        }
    }
}

int AC_automaton::Search(char* st) {
    int res = 0, t;
    Node* p = root;
    while(*st) {
        t = *st - 'a';
        while(p->next[t] == NULL && p != root)    {p = p->fail;}

        p = (p->next[t] != NULL) ? p->next[t] : root;

        Node* tmp = p;
        while(tmp != root && tmp->cnt != -1) {
            res += tmp->cnt;
            tmp->cnt = -1;
            tmp = tmp->fail;
        }
        st++;
    }
    return res;
}

char ss[1000010];

int main() {
    //Read();

    int T, n;
    scanf("%d", &T);
    while(T--) {
        AC.init();
        scanf("%d", &n);
        while(n--)  {scanf("%s", ss); AC.Insert(ss);}
        AC.Build();
        scanf("%s", ss);
        printf("%d\n", AC.Search(ss));
    }
    return 0;
}

 

病毒侵袭

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

typedef long long LL;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double inf = ~0u>>2;


using namespace std;

const int N = 10010;

struct Node {
    Node* fail;
    Node* next[130];
    int cnt;
    Node() {
        CL(next, NULL);
        fail = NULL;
        cnt = 0;
    }
};

int ans[N], tt;
bool vis[N];

class AC_automaton : public Node {
public:
    Node* root;
    int head, tail;

    void init() {root = new Node(); head = tail = 0;}

    void Insert(char*, int );
    void Build();
    int Search(char* );
}AC;

void AC_automaton::Insert(char* st, int num) {
    Node* p = root;
    while(*st) {
        int t = *st;
        if(p->next[t] == NULL) {
            p->next[t] = new Node();
        }
        p = p->next[t];
        st++;
    }
    p->cnt = num;
}

void AC_automaton::Build() {
    root->fail = NULL;
    deque<Node* > q;
    q.push_back(root);

    while(!q.empty()) {
        Node* tmp = q.front();
        Node* p = NULL;
        q.pop_front();

        for(int i = 0; i < 130; ++i) {
            if(tmp->next[i] != NULL) {
                if(tmp == root) tmp->next[i]->fail = root;
                else {
                    p = tmp->fail;
                    while(p != NULL) {
                        if(p->next[i] != NULL) {
                            tmp->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if(p == NULL)   tmp->next[i]->fail = root;
                }
                q.push_back(tmp->next[i]);
            }
        }
    }
}

int AC_automaton::Search(char* st) {
    int res = 0, t;
    Node* p = root;
    while(*st) {
        t = *st;
        while(p->next[t] == NULL && p != root)    {p = p->fail;}

        p = (p->next[t] != NULL) ? p->next[t] : root;

        Node* tmp = p;
        while(tmp != root && tmp->cnt) {
           ans[tt++] = tmp->cnt;
           // vis[tmp->cnt] = true;
            tmp = tmp->fail;
        }
        st++;
    }
    return res;
}

char ss[10010];

int main() {
    //Read();

    int N, M, i, j;
    int tol;
    while(~scanf("%d", &N)) {
        AC.init();
        for(i = 1; i <= N; ++i) {
            scanf("%s", ss);
            AC.Insert(ss, i);
        }
        AC.Build();
        tol = 0;
        scanf("%d", &M);
        for(i = 1; i <= M; ++i) {
            scanf("%s", ss);
            //CL(vis, false);
            tt = 0;

            AC.Search(ss);
            if(tt == 0) continue;
            sort(ans, ans + tt);
            printf("web %d:", i);
            for(j = 0; j < tt; ++j) {
                printf(" %d", ans[j]);
            }
            puts("");
            tol++;
        }
        printf("total: %d\n", tol);
    }
    return 0;
}

 

病毒侵袭持续中

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

typedef long long LL;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double inf = ~0u>>2;


using namespace std;

const int maxn = 1024;

struct Node {
    Node* fail;
    Node* next[26];
    int cnt;
    Node() {
        CL(next, NULL);
        fail = NULL;
        cnt = 0;
    }
};

int ans[maxn];

class AC_automaton : public Node {
public:
    Node* root;

    void init() {root = new Node();}

    void Insert(char*, int );
    void Build();
    int Search(char* );
    void DEL(Node* p) {
        for(int i = 0; i < 26; ++i)
            if(p->next[i] != NULL)  DEL(p->next[i]);
        delete p;
    }
    void Clear() {
        DEL(root);
    }
}AC;

void AC_automaton::Insert(char* st, int num) {
    Node* p = root;
    while(*st) {
        int t = *st - 'A';
        if(p->next[t] == NULL) {
            p->next[t] = new Node();
        }
        p = p->next[t];
        st++;
    }
    p->cnt = num;
}

void AC_automaton::Build() {
    root->fail = NULL;
    deque<Node* > q;
    q.push_back(root);

    while(!q.empty()) {
        Node* tmp = q.front();
        Node* p = NULL;
        q.pop_front();

        for(int i = 0; i < 26; ++i) {
            if(tmp->next[i] != NULL) {
                if(tmp == root) tmp->next[i]->fail = root;
                else {
                    p = tmp->fail;
                    while(p != NULL) {
                        if(p->next[i] != NULL) {
                            tmp->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if(p == NULL)   tmp->next[i]->fail = root;
                }
                q.push_back(tmp->next[i]);
            }
        }
    }
}

int AC_automaton::Search(char* st) {
    int res = 0, t;
    Node* p = root;
    while(*st) {
        if(!(*st >= 'A' && *st <= 'Z'))   {++st; p = root; continue ;}
        t = *st - 'A';
        while(p->next[t] == NULL && p != root)    {p = p->fail;}

        p = (p->next[t] != NULL) ? p->next[t] : root;

        Node* tmp = p;
        while(tmp != root && tmp->cnt) {
            ans[tmp->cnt]++;
            tmp = tmp->fail;
        }
        st++;
    }
    return res;
}

char tmp[1100][55];
char ss[2000010];

int main() {
    //Read();

    int n, i;
    while(~scanf("%d\n", &n)) {
        AC.init();
        for(i = 1; i <= n; ++i) {
            gets(tmp[i]);
            AC.Insert(tmp[i], i);
        }
        AC.Build();
        gets(ss);
        CL(ans, 0);
        AC.Search(ss);
        for(i = 1; i <= n; ++i) {
            if(ans[i]) {
                printf("%s: %d\n", tmp[i], ans[i]);
            }
        }
        AC.Clear();
    }
    return 0;
}

 

 

AC自动机+矩阵 

DNA Sequence

问你长度为N的串中不包含了模式串的串有几个

较为详细的讲解:http://hi.baidu.com/ccsu_010/item/7847a3c17f6fe2bc0d0a7b89

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

typedef long long LL;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double inf = ~0u>>2;


using namespace std;

const int MOD = 100000;

struct Node {
    int fail;
    int next[4];
    bool end;
    void Init() {
        CL(next, -1);
        fail = -1;
        end = 0;
    }
};

Node node[110];
int q[110];
int node_num;

int get(char c) {
    switch (c) {
        case 'A' : return 0;
        case 'G' : return 1;
        case 'C' : return 2;
        case 'T' : return 3;
        default  : return -1;
    }
}


class AC_automaton {
public:
    int head, tail;
    void Init() {
        for(int i = 0; i < 110; ++i)    node[i].Init();
        node_num = 1;
        head = tail = 0;
    }
    void Insert(char* st) {
        int t, p = 0;
        for( ; *st; ++st) {
            if(node[p].end) break;

            t = get(*st);
            if(node[p].next[t] == -1) {
                node[p].next[t] = node_num++;
            }
            p = node[p].next[t];
        }
        node[p].end = true;
    }

    void Build() {
        q[tail++] = 0;

        while(head < tail) {
            int tmp = q[head++];
            int p;
            for(int i = 0; i < 4; ++i) {
                if(node[tmp].next[i] != -1) {
                    if(tmp == 0)    node[node[tmp].next[i]].fail = 0;
                    else {
                        p = node[tmp].fail;

                        while(p != -1) {
                            if(node[p].next[i] != -1) {
                                node[node[tmp].next[i]].fail = node[p].next[i];
                                if(node[node[p].next[i]].end)   node[node[tmp].next[i]].end = 1;
                                break;
                            }
                            p = node[p].fail;
                        }
                        if(p == -1) node[node[tmp].next[i]].fail = 0;
                    }
                    q[tail++] = node[tmp].next[i];
                }
            }
        }
    }
}AC;

char ss[15];

struct Mat {
    LL mat[110][110];
}g;

Mat operator * (Mat a, Mat b) {
    Mat c;
    memset(c.mat, 0, sizeof(c.mat));
    int i, j, k;
    for(k = 0; k < node_num; ++k) {
        for(i = 0; i < node_num; ++i) {
            if(a.mat[i][k] <= 0)  continue;
            for(j = 0; j < node_num; ++j) {
                if(b.mat[k][j] <= 0)    continue;    //剪枝
                c.mat[i][j] += a.mat[i][k] * b.mat[k][j];
                if(c.mat[i][j] >= MOD)   c.mat[i][j] %= MOD;
            }
        }
    }
    return c;
}

Mat operator ^ (Mat a, int k) {
    Mat c;
    int i, j;
    for(i = 0; i < node_num; ++i)
        for(j = 0; j < node_num; ++j)
            c.mat[i][j] = (i == j);    //初始化为单位矩阵

    for(; k; k >>= 1) {
        if(k&1) c = c*a;

        a = a*a;
    }
    return c;
}

void Build_Matrix() {
    CL(g.mat, 0);
    int i, j;
    for(i = 0; i < node_num; ++i) {
        if(node[i].end) continue;
        for(j = 0; j < 4; ++j) {
            if(node[i].next[j] != -1 && node[node[i].next[j]].end == 0) g.mat[i][node[i].next[j]]++;    //goto line105

            else if(node[i].next[j] == -1) {
                if(i == 0)  {g.mat[i][i]++; continue;}
                int tmp = i;
                while(node[tmp].next[j] == -1) {
                    tmp = node[tmp].fail;
                    if(tmp == 0)    break;
                }

                if(node[tmp].next[j] != -1 && node[node[tmp].next[j]].end == 0) g.mat[i][node[tmp].next[j]]++;
                else if(node[tmp].next[j] == -1 && tmp == 0)    g.mat[i][0]++;
            }
        }
    }
}

LL solve(int n) {
    Build_Matrix();
    /*
    for(int i = 0; i < node_num; ++i) {
        for(int j = 0; j < node_num; ++j) {
            printf("%lld ", g.mat[i][j]);
        }
        puts("");
    }
    */
    g = g^n;
    LL ans = 0;
    for(int i = 0; i < node_num; ++i) {
        if(node[i].end != 0)    continue;
        ans = ans + g.mat[0][i];
        if(ans >= MOD)   ans %= MOD;
    }
    return ans;
}

int main() {
    //Read();
    //Write();

    int n, m, i;

    while(~scanf("%d%d", &m, &n)) {
        AC.Init();
        for(i = 0; i < m; ++i) {
            scanf("%s", ss);
            AC.Insert(ss);
        }
        AC.Build();
        printf("%lld\n", solve(n));
    }
    return 0;
}

 

 

 

 

 

 

 

AC自动机+DP

 

DNA REPAIR

给定n个疾病DNA序列,和一个待修复序列str。用最小的次数修改待修复序列,使其不含疾病DNA序列。

dp[i][j]表示跑到母串第i位置,自动机上j状态时最小改变的字符数;

dp[i+1][tmp] = min(dp[i+1][tmp], dp[i][j] + (st[i] ==k)); k表示从j状态到达tmp状态所走的边(注意区分dp的状态和自动机的状态)

View Code
//#pragma comment(linker,"/STACK:327680000,327680000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

typedef long long LL;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = ~0u>>2;


using namespace std;

const int maxn = 1024;

struct Node {
    int fail;
    int next[4];
    int cnt;
    bool end;
    void init() {
        fail = -1;
        cnt = 0;
        CL(next, -1);
        end = false;
    }
};

Node node[maxn];
int node_num;
int dp[maxn][maxn];
int q[maxn];

int get(char c) {
    switch(c) {
        case 'A' : return 0;
        case 'T' : return 1;
        case 'G' : return 2;
        case 'C' : return 3;
        default  : return -1;
    }
}

class AC_automaton {
public:
    int head, tail;
    void init() {
        for(int i = 0; i < maxn; ++i)   node[i].init();
        head = tail = 0;
        node_num = 1;
    }
    void Insert(char* st) {
        int p = 0, t;
        for( ; *st; ++st) {
            t = get(*st);
            if(node[p].end) break;
            if(node[p].next[t] == -1) {
                node[p].next[t] = node_num++;
            }
            p = node[p].next[t];
        }
        node[p].end = true;
    }
    void Build() {
        int tmp, p, i;
        q[tail++] = 0;

        while(head < tail) {
            tmp = q[head++];
            for(i = 0; i < 4; ++i) {
                if(node[tmp].next[i] == -1) continue;
                if(tmp == 0)    node[node[tmp].next[i]].fail = 0;
                else {
                    p = node[tmp].fail;
                    while(p != -1) {
                        if(node[p].next[i] != -1) {
                            node[node[tmp].next[i]].fail = node[p].next[i];
                            if(node[node[p].next[i]].end)   node[node[tmp].next[i]].end = true;
                            break;
                        }
                        p = node[p].fail;
                    }
                    if(p == -1) node[node[tmp].next[i]].fail = 0;
                }
                q[tail++] = node[tmp].next[i];
            }
        }
    }
    int search(char* st) {
        int res = 0, t;
        int p = 0;

        for( ; *st; ++st) {
            t = get(*st);
            while(node[p].next[t] == -1 && p != 0)  p = node[p].fail;
            p = node[p].next[t];
            if(p == -1) p = 0;
            int tmp = p;
            while(tmp != 0 && node[tmp].cnt ) {
                res += node[tmp].cnt;
                node[tmp].cnt = -1;
                tmp = node[tmp].fail;
            }
        }
        return res;
    }
}AC;

char st[maxn];

int solve() {
    int i, j, k, tmp, len = strlen(st);
    for(i = 0; i <= len; ++i) {
        for(j = 0; j <= node_num; ++j)   dp[i][j] = inf;
    }
    dp[0][0] = 0;

    for(i = 0; i < len; ++i) {
        for(j = 0; j < node_num; ++j) {
            if(dp[i][j] == inf)  continue;
            for(k = 0; k < 4; ++k) {
                tmp = j;
                while(tmp != -1) {
                    if(node[tmp].next[k] != -1) {tmp = node[tmp].next[k]; break;}
                    tmp = node[tmp].fail;
                }
                if(tmp == -1)   tmp = 0;
                if(node[tmp].end == false)  dp[i+1][tmp] = min(dp[i+1][tmp], dp[i][j] + (get(st[i]) != k));
            }
        }
    }
    int ans = inf;
    for(j = 0; j < node_num; ++j) {
        ans = min(ans, dp[len][j]);
    }
    return ans == inf ? -1 : ans;
}


int main() {
    //Read();

    int n, i, cas = 0;
    while(scanf("%d", &n), n) {
        AC.init();
        for(i = 0; i < n; ++i) {
            scanf("%s", st);
            AC.Insert(st);
        }
        scanf("%s", st);
        AC.Build();
        printf("Case %d: %d\n", ++cas, solve());
    }
    return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2012-11-06 10:03  AC_Von  阅读(493)  评论(0编辑  收藏  举报