您的位置:首页 > 其它

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

2017-09-20 09:32 381 查看

题目链接

题意

给定 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

思路

找到最长的串作为主串,其它 n−1 个串作为模式串,跑 n−1 遍 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

思路

对其他 n−1 个串建 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: