HDU 6208 The Dominator of Strings 读入挂+kmp / AC自动机

10 篇文章 0 订阅
9 篇文章 0 订阅

题目链接

题意

给定 n 个串,问是否存在一个串包含其它所有串。

读入的问题

The total length of strings in each case has the limit of 100000.
The limit is 30MB for the input file.

考虑将所有的串读到一整个串里,记录每个串在其中的开始位置和长度

注意:这种情况下,如果每个串末尾有 '\0',则开的长度不是 100000 而是 200000

法一:kmp 546ms

思路

找到最长的串作为主串,其它 n1 个串作为模式串,跑 n1 kmp

Code

#include <bits/stdc++.h>
#define maxm 200010
const int BUF_SIZE = (int)1e4+10;
using namespace std;
int f[maxm];
char s[maxm], ans[maxm];
struct node {
    int beg, len;
    node(int _a=0, int _b=0) : beg(_a), len(_b) {}
}nd[maxm];
struct fastIO {
    char buf[BUF_SIZE];
    int cur;
    FILE *in, *out;
    fastIO() {
        cur = BUF_SIZE;
        in = stdin;
        out = stdout;
    }
    inline char nextChar() {
        if(cur == BUF_SIZE) {
            fread(buf, BUF_SIZE, 1, in);
            cur = 0;
        }
        return buf[cur++];
    }
    inline int nextInt() {
        int x = 0;
        char c = nextChar();
        while(!('0' <= c && c <= '9')) c = nextChar();
        while('0' <= c && c <= '9') {
            x = x * 10 + c - '0';
            c = nextChar();
        }
        return x;
    }
    inline int nextString(char* s) {
        char c = nextChar();
        int len = 0;
        while(!('a' <= c && c <= 'z')) c = nextChar();
        while('a' <= c && c <= 'z') s[len++] = c, c = nextChar();
        return len;
    }
    inline void printChar(char ch) {
        buf[cur++] = ch;
        if (cur == BUF_SIZE) {
            fwrite(buf, BUF_SIZE, 1, out);
            cur = 0;
        }
    }
    inline void printInt(int x) {
        if (x >= 10) printInt(x / 10);
        printChar(x % 10 + '0');
    }
    inline void close() {
        if (cur > 0) {
            fwrite(buf, cur, 1, out);
        }
        cur = 0;
    }
} IO;
void getfail(char* P, int m) {
    f[0] = f[1] = 0;
    for (int i = 1; i < m; ++i) {
        int j = f[i];
        while (j && P[j] != P[i]) j = f[j];
        f[i+1] = P[j] == P[i] ? j+1 : 0;
    }
}
bool kmp(char* T, int n, char* P, int m) {
    getfail(P, m);
    int j = 0;
    for (int i = 0; i < n; ++i) {
        while (j && T[i] != P[j]) j = f[j];
        if (T[i] == P[j]) ++j;
        if (j == m) return true;
    }
    return false;
}
int kas = 0;
void work() {
    int n;
    n = IO.nextInt();
    memset(s, 0, sizeof(s));
    int mx = -1, p = -1, cur = 0;
    for (int i = 0; i < n; ++i) {
        int temp = cur;
        int len = IO.nextString(s+cur);
        nd[i] = node(cur, len);
        if (len > mx) mx = len, p = i;
        cur += len+1;
    }
    for (int i = 0; i < n; ++i) {
        if (p == i) continue;
        if (!kmp(s+nd[p].beg, nd[p].len, s+nd[i].beg, nd[i].len)) { printf("No\n"); return; }
    }
    printf("%s\n", s+nd[p].beg);
}

int main() {
    int T;
    T = IO.nextInt();
    while (T--) work();
    return 0;
}

法二:AC自动机 2121ms

思路

对其他 n1 个串建 AC 自动机,拿最长的串在上面跑一遍。

Code

#include <bits/stdc++.h>
#define maxm 100010
const int BUF_SIZE = (int)1e4+10;
using namespace std;
int son[maxm][26], fail[maxm], cnt[maxm], tot;
char s[maxm * 2];
struct node {
    int beg, len;
    node(int _a=0, int _b=0) : beg(_a), len(_b) {}
}nd[maxm];
struct fastIO {
    char buf[BUF_SIZE];
    int cur;
    FILE *in, *out;
    fastIO() {
        cur = BUF_SIZE;
        in = stdin;
        out = stdout;
    }
    inline char nextChar() {
        if(cur == BUF_SIZE) {
            fread(buf, BUF_SIZE, 1, in);
            cur = 0;
        }
        return buf[cur++];
    }
    inline int nextInt() {
        int x = 0;
        char c = nextChar();
        while(!('0' <= c && c <= '9')) c = nextChar();
        while('0' <= c && c <= '9') {
            x = x * 10 + c - '0';
            c = nextChar();
        }
        return x;
    }
    inline int nextString(char* s) {
        char c = nextChar();
        int len = 0;
        while(!('a' <= c && c <= 'z')) c = nextChar();
        while('a' <= c && c <= 'z') s[len++] = c, c = nextChar();
        return len;
    }
    inline void printChar(char ch) {
        buf[cur++] = ch;
        if (cur == BUF_SIZE) {
            fwrite(buf, BUF_SIZE, 1, out);
            cur = 0;
        }
    }
    inline void printInt(int x) {
        if (x >= 10) printInt(x / 10);
        printChar(x % 10 + '0');
    }
    inline void close() {
        if (cur > 0) {
            fwrite(buf, cur, 1, out);
        }
        cur = 0;
    }
} IO;
void add(char* s, int len) {
    int p = 0;
    for (int i = 0; i < len; ++i) {
        if (son[p][s[i]-'a'] == -1) {
            cnt[++tot] = 0;
            for (int j = 0; j < 26; ++j) son[tot][j] = -1;
            son[p][s[i]-'a'] = tot;
        }
        p = son[p][s[i]-'a'];
    }
    ++cnt[p];
}
void build() {
    queue<int> que;
    fail[0] = 0;
    for (int i = 0; i < 26; ++i) {
        if (son[0][i] == -1) son[0][i] = 0;
        else {
            fail[son[0][i]] = 0;
            que.push(son[0][i]);
        }
    }
    while (!que.empty()) {
        int x = que.front(); que.pop();
        for (int i = 0; i < 26; ++i) {
            if (son[x][i] == -1) son[x][i] = son[fail[x]][i];
            else {
                fail[son[x][i]] = son[fail[x]][i];
                que.push(son[x][i]);
            }
        }
    }
}
int query(char* s, int len) {
    int p = 0, ret = 0;
    for (int i = 0; i < len; ++i) {
        p = son[p][s[i]-'a'];
        int temp = p;
        while (temp) {
            if (cnt[temp] == -1) break;
            ret += cnt[temp];
            cnt[temp] = -1;
            temp = fail[temp];
        }
    }
    return ret;
}
int kas = 0;
void init() {
    memset(s, 0, sizeof(s)); cnt[tot = 0] = 0;
    for (int i = 0; i < 26; ++i) son[0][i] = -1;
}
void work() {
    init();
    int n;
    n = IO.nextInt();
    int mx = -1, p = -1, cur = 0;
    for (int i = 0; i < n; ++i) {
        int temp = cur;
        int len = IO.nextString(s+cur);
        nd[i] = node(cur, len);
        if (len > mx) mx = len, p = i;
        cur += len+1;
        add(s+nd[i].beg, nd[i].len);
    }
    build();
    if (query(s+nd[p].beg, nd[p].len) == n) printf("%s\n", s+nd[p].beg);
    else printf("No\n");
}

int main() {
    int T;
    T = IO.nextInt();
    while (T--) work();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值