P1470 [USACO2.3] Longest Prefix 题解
题意
求用一堆小字符串能拼出
思路
前置:KMP。
先用 KMP 求出在
最后特判一下,如果没有任何线段的左端点为
代码
#include <bits/stdc++.h>
using namespace std;
int t, n, m, cnt, ans, now, cntp, lent, len[10000005], nxt[15];
char s[10000005], c[10000005], tmp[10000005], st[10000005][15];
struct node {
int id, len;
} pos[10000005];
inline bool cmp(node x, node y) {
if (x.id == y.id)
return x.len < y.len;
return x.id < y.id;
}
inline void solve(char p[]) {
m = strlen(p + 1);
memset(nxt, 0, sizeof nxt);
for (int i = 2, j = 0; i <= m; i++) {
while (j && p[j + 1] != p[i])
j = nxt[j];
if (p[j + 1] == p[i])
j++;
nxt[i] = j;
}
}
inline void mate(char p[]) {
m = strlen(p + 1);
for (int i = 1, j = 0; i <= n; i++) {
while (j && s[i] != p[j + 1])
j = nxt[j];
if (s[i] == p[j + 1])
j++;
if (j == m)
pos[++cntp].id = i - m + 1, pos[cntp].len = m, j = nxt[j];
}
}
int main() {
while (1) {
scanf("%s", c + 1);
if (c[1] == '.')
break;
t = strlen(c + 1), cnt++;
for (int i = 1; i <= t; i++) {
st[cnt][i] = c[i];
}
}
while (~scanf("%s", tmp + 1)) {
lent = strlen(tmp + 1);
for (int i = 1; i <= lent; i++) {
s[++n] = tmp[i];
}
}
for (int i = 1; i <= cnt; i++) {
solve(st[i]), mate(st[i]);
}
sort(pos + 1, pos + 1 + cntp, cmp);
if (pos[1].id > 1) {
cout << 0;
return 0;
}
for (int i = 1; i <= cntp; i++) {
if (pos[i].id <= now + 1) {
now = max(now, pos[i].id + pos[i].len - 1);
}
}
cout << min(now, n);
return 0;
}