AC自动机练习解题题集

需要提前学习AC自动机的知识点:

大牛的AC自动机详解


HDU 2222 Keywords Search (传送门)

题意

求目标串中出现了几种模式串

解题思路

裸的 AC  自动机,使用一个标志模式串结尾的 end  数组,查询一次,将相应的 end  数组清零即可。

代码

/*头文件模板*/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

#define pb push_back
#define mp make_pair
#define mem(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a))
#define lson rt << 1, l, mid
#define rson rt << 1|1, mid + 1, r
#define FIN freopen("input.txt", "r", stdin)
#define FOUT freopen("output.txt", "w", stdout)

typedef long long LL;
typedef pair<int, int > PII;
typedef pair<int, string> PIS;
typedef pairPLL;
typedef unsigned long long uLL;

template<typename T>
void print (T* p, T* q, string Gap = " ", bool flag = false) {
    int d = p < q ? 1 : -1;
    while (p != q) {
        if (flag) cout << Gap[0] << *p << Gap[1];
        else cout << *p;
        p += d;
        if (p != q && !flag) cout << Gap;
    }
    cout << endl;
}

template<typename T>
void print (const T &a, string bes = "") {
    int len = bes.length();
    if (len >= 2) cout << bes[0] << a << bes[1] << endl;
    else cout << a << endl;
}

template<typename T>
void debug (T* p, T* q, string Gap = " ", bool flag = false) {
#ifndef ONLINE_JUDGE
    int d = p < q ? 1 : -1;
    cout << "Debug out : ";
    while (p != q) {
        if (flag) cout << Gap[0] << *p << Gap[1];
        else cout << *p;
        p += d;
        if (p != q && !flag) cout << Gap;
    }
    cout << endl;
#endif
}

template<typename T>
void debug (const T &a, string bes = "") {
#ifndef ONLINE_JUDGE
    int len = bes.length();
    cout << "Debug out : ";
    if (len >= 2) cout << bes[0] << a << bes[1] << endl;
    else cout << a << endl;
#endif
}

void IO_Init() {
    ios::sync_with_stdio (false);
}

LL LLabs (const LL a) {
    return a >= 0 ? a : -a;
}

const double PI = 3.1415926535898;
const double eps = 1e-10;
const int MAXM = 1e5 + 5;
const int MAXN = 1e6 + 5;
const int INF = 0x3f3f3f3f;

/*头文件模板*/

struct AC {


    struct node {
        int end;
        int next[27];
        void init() {
            end = 0;
            mem(next, -1);
        }
    };


    int tot, fail[MAXN];
    node L[MAXN];


    void init() {
        tot = 0;
        L[tot].init();
    }

    void insert(char buf[]) {
        int slen = strlen(buf);
        int now = 0;
        for(int i = 0; i < slen; i ++) {
            int tmp = buf[i] - 'a';
            int next = L[now].next[tmp];
            if(next == -1) {
                next = ++ tot;
                L[next].init();
                L[now].next[tmp] = next;
            }
            now = next;
        }
        L[now].end ++;
    }

    void build() {
        queue<int>Q;
        int root = 0;
        fail[root] = root;
        for(int i = 0;i < 26;i ++){
            if(L[root].next[i] == -1){
                L[root].next[i] = root;
            }
            else{
                fail[L[root].next[i]] = root;
                Q.push(L[root].next[i]);
            }
        }

        while(!Q.empty()){
            int now = Q.front();
            Q.pop();
            for(int i = 0;i < 26;i ++){
                if(L[now].next[i] == -1){
                    L[now].next[i] = L[fail[now]].next[i];
                }
                else{
                    fail[L[now].next[i]] = L[fail[now]].next[i];
                    Q.push(L[now].next[i]);
                }
            }
        }
    }

    int query(char buf[]){
        int slen = strlen(buf);
        int now = 0, res = 0;
        for(int i = 0;i < slen;i ++){
            int tmp = buf[i] - 'a';
            int p = L[now].next[tmp];
            now = p;
            while(p){
                res += L[p].end;
                L[p].end = 0;
                p = fail[p];
            }
        }
        return res;
    }


};

int T, n;
char buf[MAXN];
AC ac;

int main() {
#ifndef ONLINE_JUDGE
    //FIN;
    //FOUT;
#endif
    IO_Init();
    scanf("%d", &T);
    while(T --){
        ac.init();
        scanf("%d", &n);
        for(int i = 0;i < n;i ++){
            scanf("%s", buf);
            ac.insert(buf);
        }
        ac.build();
        scanf("%s", buf);
        printf("%d\n", ac.query(buf));
    }
    return 0;
}

HDU 2896 病毒侵袭 (传送门)

题意

输出出现模式串的 id  和有模式串的字符串的个数

解题思路

end  记录 id  就可以了,同时注意 [  以上字符串中字符都是ASCII码可见字符] ,所以字典树最少需要开 128  大小的数组.

代码

/*头文件模板*/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

#define pb push_back
#define mp make_pair
#define mem(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a))
#define lson rt << 1, l, mid
#define rson rt << 1|1, mid + 1, r
#define FIN freopen("input.txt", "r", stdin)
#define FOUT freopen("output.txt", "w", stdout)

typedef long long LL;
typedef pair<int, int > PII;
typedef pair<int, string> PIS;
typedef pairPLL;
typedef unsigned long long uLL;

template<typename T>
void print (T* p, T* q, string Gap = " ", bool flag = false) {
    int d = p < q ? 1 : -1;
    while (p != q) {
        if (flag) cout << Gap[0] << *p << Gap[1];
        else cout << *p;
        p += d;
        if (p != q && !flag) cout << Gap;
    }
    cout << endl;
}

template<typename T>
void print (const T &a, string bes = "") {
    int len = bes.length();
    if (len >= 2) cout << bes[0] << a << bes[1] << endl;
    else cout << a << endl;
}

template<typename T>
void debug (T* p, T* q, string Gap = " ", bool flag = false) {
#ifndef ONLINE_JUDGE
    int d = p < q ? 1 : -1;
    cout << "Debug out : ";
    while (p != q) {
        if (flag) cout << Gap[0] << *p << Gap[1];
        else cout << *p;
        p += d;
        if (p != q && !flag) cout << Gap;
    }
    cout << endl;
#endif
}

template<typename T>
void debug (const T &a, string bes = "") {
#ifndef ONLINE_JUDGE
    int len = bes.length();
    cout << "Debug out : ";
    if (len >= 2) cout << bes[0] << a << bes[1] << endl;
    else cout << a << endl;
#endif
}

void IO_Init() {
    ios::sync_with_stdio (false);
}

LL LLabs (const LL a) {
    return a >= 0 ? a : -a;
}

const double PI = 3.1415926535898;
const double eps = 1e-10;
const int MAXM = 1e5 + 5;
const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;

/*头文件模板*/

struct AC {
    struct node {
        int end;
        int next[128];
        void init() {
            end = 0;
            mem(next, -1);
        }
    };

    int tot, fail[MAXN];
    node L[MAXN];

    void init() {
        tot = 0;
        L[0].init();
        mem(fail, 0);
    }

    void insert(char buf[], int d) {
        int slen = strlen(buf);
        int now = 0;
        for(int i = 0; i < slen; i ++) {
            int tmp = buf[i];
            int next = L[now].next[tmp];
            if(next == -1) {
                next = ++ tot;
                L[next].init();
                L[now].next[tmp] = next;
            }
            now = next;
        }
        L[now].end = d;
    }

    void build() {
        queue<int>Q;
        int root = 0;
        fail[root] = root;
        for(int i = 0; i < 128; i ++) {
            if(L[root].next[i] == -1) {
                L[root].next[i] = root;
            } else {
                fail[L[root].next[i]] = root;
                Q.push(L[root].next[i]);
            }
        }

        while(!Q.empty()) {
            int now = Q.front();
            Q.pop();
            for(int i = 0; i < 128; i ++) {
                if(L[now].next[i] == -1) {
                    L[now].next[i] = L[fail[now]].next[i];
                } else {
                    fail[L[now].next[i]] = L[fail[now]].next[i];
                    Q.push(L[now].next[i]);
                }
            }
        }
    }

    vector<int> query(char buf[]) {
        vector<int>V;
        int slen = strlen(buf);
        int now = 0;
        for(int i = 0;i < slen;i ++){
            int tmp = buf[i];
            int p = L[now].next[tmp];
            now = p;
            while(p){
                if(L[p].end != 0) V.pb(L[p].end);
                p = fail[p];
            }
        }
        sort(V.begin(), V.end());
        V.erase(unique(V.begin(), V.end()), V.end());
        return V;
    }

} ac;


int N, M;
char bd[MAXN], web[MAXN];

int main() {
#ifndef ONLINE_JUDGE
    //FIN;
    //FOUT;
#endif
    IO_Init();
    ac.init();
    scanf("%d", &N);
    for(int i = 1; i <= N; i ++) {
        scanf("%s", bd);
        ac.insert(bd, i);
    }

    ac.build();

    scanf("%d", &M);
    vector<int>bV;
    int ans = 0;
    for(int i = 1; i <= M; i ++) {
        scanf("%s", web);
        bV = ac.query(web);
        if(bV.size() > 0) {
            ans ++;
            printf("web %d:", i);
            for(int j = 0; j < bV.size(); j ++) {
                printf(" %d", bV[j]);
            }
            printf("\n");
        }
    }
    printf("total: %d\n", ans);
    return 0;
}

HDU 3065 病毒侵袭持续中(传送门)

题意

输出每个模式串出现的次数

解题思路

直接用数组记录一下就可以了, [  题目有一丢丢小问题,要多组输入] 

代码

/*头文件模板*/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

#define pb push_back
#define mp make_pair
#define mem(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a))
#define lson rt << 1, l, mid
#define rson rt << 1|1, mid + 1, r
#define FIN freopen("input.txt", "r", stdin)
#define FOUT freopen("output.txt", "w", stdout)

typedef long long LL;
typedef pair<int, int > PII;
typedef pair<int, string> PIS;
typedef pairPLL;
typedef unsigned long long uLL;

template<typename T>
void print (T* p, T* q, string Gap = " ", bool flag = false) {
    int d = p < q ? 1 : -1;
    while (p != q) {
        if (flag) cout << Gap[0] << *p << Gap[1];
        else cout << *p;
        p += d;
        if (p != q && !flag) cout << Gap;
    }
    cout << endl;
}

template<typename T>
void print (const T &a, string bes = "") {
    int len = bes.length();
    if (len >= 2) cout << bes[0] << a << bes[1] << endl;
    else cout << a << endl;
}

template<typename T>
void debug (T* p, T* q, string Gap = " ", bool flag = false) {
#ifndef ONLINE_JUDGE
    int d = p < q ? 1 : -1;
    cout << "Debug out : ";
    while (p != q) {
        if (flag) cout << Gap[0] << *p << Gap[1];
        else cout << *p;
        p += d;
        if (p != q && !flag) cout << Gap;
    }
    cout << endl;
#endif
}

template<typename T>
void debug (const T &a, string bes = "") {
#ifndef ONLINE_JUDGE
    int len = bes.length();
    cout << "Debug out : ";
    if (len >= 2) cout << bes[0] << a << bes[1] << endl;
    else cout << a << endl;
#endif
}

void IO_Init() {
    ios::sync_with_stdio (false);
}

LL LLabs (const LL a) {
    return a >= 0 ? a : -a;
}

const double PI = 3.1415926535898;
const double eps = 1e-10;
const int MAXM = 1e5 + 5;
const int MAXN = 1e6 + 5;
const int INF = 0x3f3f3f3f;

/*头文件模板*/

struct AC {
    struct node {
        int end;
        int next[128];
        void init() {
            end = 0;
            mem(next, -1);
        }
    };

    int tot, fail[MAXN];
    node L[MAXN];

    void init() {
        tot = 0;
        L[0].init();
        mem(fail, 0);
    }

    void insert(char buf[], int d) {
        int slen = strlen(buf);
        int now = 0;
        for(int i = 0; i < slen; i ++) {
            int tmp = buf[i];
            int next = L[now].next[tmp];
            if(next == -1) {
                next = ++ tot;
                L[next].init();
                L[now].next[tmp] = next;
            }
            now = next;
        }
        L[now].end = d;
    }

    void build() {
        queue<int>Q;
        int root = 0;
        fail[root] = root;
        for(int i = 0; i < 128; i ++) {
            if(L[root].next[i] == -1) {
                L[root].next[i] = root;
            } else {
                fail[L[root].next[i]] = root;
                Q.push(L[root].next[i]);
            }
        }

        while(!Q.empty()) {
            int now = Q.front();
            Q.pop();
            for(int i = 0; i < 128; i ++) {
                if(L[now].next[i] == -1) {
                    L[now].next[i] = L[fail[now]].next[i];
                } else {
                    fail[L[now].next[i]] = L[fail[now]].next[i];
                    Q.push(L[now].next[i]);
                }
            }
        }
    }

    void query(char buf [], int K[]) {
        int slen = strlen(buf);
        int now = 0;
        for(int i = 0; i < slen; i ++) {
            int tmp = buf[i];
            int p = L[now].next[tmp];
            now = p;
            while(p) {
                K[L[p].end] ++;
                p = fail[p];
            }
        }
    }


} ac;


int N, M;
char bd[60], web[MAXN << 1];
string T1[1000 + 5];
int Vnum[1000 + 5];
int main() {
#ifndef ONLINE_JUDGE
    //FIN;
    //FOUT;
#endif
    IO_Init();

    while(~scanf("%d", &N)) {
        ac.init();
        mem(Vnum, 0);
        for(int i = 1; i <= N; i ++) {
            scanf("%s", bd);
            T1[i] = string(bd);
            ac.insert(bd, i);
        }
        ac.build();
        scanf("%s", web);
        ac.query(web, Vnum);
        for(int i = 1; i <= N; i ++) {
            if(Vnum[i] > 0) {
                cout << T1[i] << ": " << Vnum[i] << endl;
            }
        }
    }
    return 0;
}

你可能感兴趣的:(ACM_字符串处理)