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;
}

posted @ 2012-05-08 18:48  LETTers  阅读(151)  评论(0编辑  收藏  举报