BZOJ4032 [HEOI2015]最短不公共子串
Description
在虐各种最长公共子串、子序列的题虐的不耐烦了之后,你决定反其道而行之。
一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是。
一个串的“子序列”指的是它的可以不连续的一段,例如bde是abcdef的子串,但bdd不是。
下面,给两个小写字母串A,B,请你计算:
(1) A的一个最短的子串,它不是B的子串
(2) A的一个最短的子串,它不是B的子序列
(3) A的一个最短的子序列,它不是B的子串
(4) A的一个最短的子序列,它不是B的子序列
Input
有两行,每行一个小写字母组成的字符串,分别代表A和B。
Output
输出4行,每行一个整数,表示以上4个问题的答案的长度。如果没有符合要求的答案,输出-1.
Sample Input
aabbcc
abcabc
abcabc
Sample Output
2
4
2
4
4
2
4
HINT
对于100%的数据,A和B的长度都不超过2000
题解
如果都是子串,那么直接在后缀自动机上BFS即可;否则,可以乱搞出什么“子序列自动机”(只需要把每个节点连到它的下一个a、下一个b、...下一个z即可),然后bfs。
(为了一句last=ne调了一个小时QAQ)
附代码:
#include <algorithm>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <queue>
const int N = 4050;
struct Node{
int nxt[26], pa, len;
};
struct Automation{
Node nodes[N];
int cnt;
inline int newNode(int l = 0) {
memcpy(&nodes[cnt].nxt, &nodes[l].nxt, sizeof(int) * 26);
nodes[cnt].pa = nodes[l].pa;
nodes[cnt].len = nodes[l].len;
return cnt++;
}
int root;
int seq_last[26], last;
void init() {
memset(&nodes[0], 0, sizeof(Node));
cnt = 1;
root = newNode();
for (int i = 0; i < 26; ++i)
seq_last[i] = root;
last = root;
}
void seq_append(int x) {
int ne = newNode();
for (int i = 0; i < 26; ++i)
for (int q = seq_last[i]; q && !nodes[q].nxt[x]; q = nodes[q].pa)
nodes[q].nxt[x] = ne;
nodes[ne].pa = seq_last[x];
seq_last[x] = ne;
}
void suffix_append(int x) {
int ne = newNode();
nodes[ne].len = nodes[last].len + 1;
int q = last;
while (q && !nodes[q].nxt[x]) {
nodes[q].nxt[x] = ne;
q = nodes[q].pa;
}
if (!q) {
nodes[last = ne].pa = root;
return;
}
int p = nodes[q].nxt[x];
if (nodes[p].len == nodes[q].len + 1) {
nodes[last = ne].pa = p;
return;
}
int pq = newNode(p);
nodes[pq].len = nodes[q].len + 1;
nodes[last = ne].pa = nodes[p].pa = pq;
while (q && nodes[q].nxt[x] == p) {
nodes[q].nxt[x] = pq;
q = nodes[q].pa;
}
}
};
struct AAA{
int x, y, len;
AAA(int a, int b, int c) : x(a), y(b), len(c) {}
};
std::bitset<N> vis[N];
std::queue<AAA> Q;
int bfs(const Automation &A, const Automation &B) {
while (!Q.empty()) Q.pop();
Q.push(AAA(A.root, B.root, 0));
for (int i = 0; i < A.cnt; ++i)
vis[i].reset();
vis[A.root][B.root] = 1;
while (!Q.empty()) {
AAA x = Q.front(); Q.pop();
const Node &a = A.nodes[x.x], &b = B.nodes[x.y];
for (int i = 0; i < 26; ++i) {
int l = a.nxt[i], r = b.nxt[i];
if (!l) continue;
if (!r) return x.len + 1;
if (!vis[l][r]) Q.push(AAA(l, r, x.len + 1));
vis[l][r] = 1;
}
}
return -1;
}
Automation a, b;
char s[N], p[N];
int main() {
scanf("%s%s", s, p);
a.init();
for (char *r = s; *r; ++r)
a.suffix_append(*r - 'a');
b.init();
for (char *r = p; *r; ++r)
b.suffix_append(*r - 'a');
printf("%d\n", bfs(a, b));
b.init();
for (char *r = p; *r; ++r)
b.seq_append(*r - 'a');
printf("%d\n", bfs(a, b));
a.init();
for (char *r = s; *r; ++r)
a.seq_append(*r - 'a');
int ans4 = bfs(a, b);
b.init();
for (char *r = p; *r; ++r)
b.suffix_append(*r - 'a');
printf("%d\n", bfs(a, b));
printf("%d\n", ans4);
return 0;
}

浙公网安备 33010602011771号