LETTers练习赛第十场 第三题
这题感觉 lcp 还是必须的,时限卡得比较紧,所以就只能扩展 kmp 了。但是比起后缀系列的 lcp ,扩展 kmp 能求的 lcp 还是有一些限制的。本题中,对于一些情况,就不得不用循环复制的方法,将问题化解。大致可以分为 3 种情况,具体就看图吧。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 100000
#define max(x,y) x>y?x:y
void get_self_lcp(char *t, int lt, int *lcp) {
int j = 0, k;
while (j + 1 < lt && t[j] == t[j + 1])
++j;
lcp[1] = j; k = 1;
for (int i = 2; i < lt; ++i) {
int len = k + lcp[k] - 1, l = lcp[i - k];
if (l < len - i + 1)
lcp[i] = l;
else {
j = max(0, len - i + 1);
while (i + j < lt && t[j] == t[i + j])
++j;
lcp[i] = j; k = i;
}
}
}
void ext_kmp(char *s, int ls, int *lcp1, char *t, int lt, int *lcp2) {
get_self_lcp(t, lt, lcp2);
int j = 0, k;
while (j < ls && j < lt && s[j] == t[j])
++j;
lcp1[0] = j; k = 0;
for (int i = 1; i < ls; ++i) {
int len = k + lcp1[k] - 1, l = lcp2[i - k];
if (l < len - i + 1)
lcp1[i] = l;
else {
j = max(0, len - i + 1);
while (i + j < ls && j < lt && s[i + j] == t[j])
++j;
lcp1[i] = j; k = i;
}
}
}
int lcp1[MAXN + 2], lcp2[MAXN + 2];
char s1[MAXN + 2], s2[MAXN + 2];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int i;
while (scanf("%s%s", s1, s2) != EOF) {
int len = strlen(s1), l2 = strlen(s2);
for (i = 0; i < len; ++i)
s2[i] = s2[i % l2];
ext_kmp(s1, len, lcp1, s2, max(len, l2), lcp2);
int ip = len;
for (i = len - 1; i >= 0; --i) {
int lm = lcp1[i];
if (i + lm < ip) {
if (s2[lm] < s1[i + lm])
ip = i;
} else {
if (ip - i >= l2) {
lm = lcp1[ip - l2 + 1];
if (lm < l2 && s1[ip - l2 + 1 + lm] < s2[lm])
ip = i;
} else {
lm = lcp2[ip - i];
if (lm < l2 && s2[ip - i + lm] < s2[lm])
ip = i;
}
}
}
for (i = 0; i < ip; ++i)
putchar(s1[i]);
s2[l2] = 0;
printf("%s%s\n", s2, s1 + ip);
}
return 0;
}