Pertozavodsk Winter Training Camp 2016-Problem K. Two Strings

Time limit: 2.5 seconds
Memory limit: 768 mebibytes

  • You are given two strings S = S 0 S_{0} S0 S 1 S_{1} S1 · · · S ∣ S ∣ − 1 S_{|S|−1} SS1and T = T 0 T_{0} T0 T 1 T_{1} T1 · · · T ∣ T ∣ − 1 T_{|T|−1} TT1 consisting of lowercase letters. Here |S| is the length of thestring S. The substring S[l, r] (0 ≤ l ≤ r < |S|) of the string S = S 0 S_{0} S0 S 1 S_{1} S1 · · · S ∣ S ∣ − 1 S_{|S|−1} SS1 is the string S = S l S_{l} Sl S l + 1 S_{l+1} Sl+1 · · · S r S_{r} Sr. Define the function F(S, l, r) for the string S and two integers l, r as follows: F(S, l ,r) = r − l − max(l, |S| − r − 1) + 1. In other words, F is the length of the substring minus the maximum distance from borders of S to the substring. Your task is to find a substring S[l, r] such that it occurs in T as substring and the value F(S, l, r) is maximum among all pairs (l, r) (0 ≤ l ≤ r < |S|).

Input

  • The first two lines contain strings S and T, respectively (1 ≤ |S|, |T| ≤ 106 ). Strings S and T consist of lowercase English letters.

Output

  • If no substring of string S occurs in the string T, print a single string “−1 −1” (without quotes). Otherwise, print two integers l and r such that F(S, l, r) is maximum among all possible pairs (l, r) (0 ≤ l ≤ r < |S|) and S[l, r] is a substring of T. If there are several possible pairs, print the lexicographically smallest one.

Examples

input               output
riveragesmalir           4 5
toaxernaturaln

aaaaa               0 4
aaaaa

amkar               -1 -1
zenit

Note
Pair ( l 1 l_{1} l1, r 1 r_{1} r1) is lexicographically less than pair ( l 2 l_{2} l2, r 2 r_{2} r2) if either l 1 l_{1} l1 < l 2 l_{2} l2, or l 1 l_{1} l1 = l 2 l_{2} l2 and r 1 r_{1} r1 < r 2 r_{2} r2.

题意

  • 在第一个串中找到一个子串同时属于题目所给的两个串的子串,同时价值要最大,价值是 子串的长度减去(第一个串的左边界到该子串的左边界和右边界到该子串的右边界的较大值)

题解

  • 其实主要就是找到属于S的子串同时也属于T的,所以我们容易想到后缀数组,把两个串接起来,做个后缀数组,然后就可以知道最长前缀,也就是以每个位置的最长公共子串,但这样的做法常数太大,会tle,所以我们用后缀自动机,常数小些,先将T串建在后缀自动机上,然后用S串去跑,在过程中更新答案,看代码就可以很容易理解
#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e6+9;
const int INF = 0x3f3f3f3f;

char s[maxn],t[maxn];

struct sam{
    int len[maxn<<1],link[maxn << 1],ch[maxn<<1][26];
    int num[maxn<<1];
    int sz,rt,last;
    int newnode(int x = 0){
        len[sz] = x;
        link[sz] = -1;
        memset(ch[sz],-1,sizeof(ch[sz]));
        return sz++;
    }
    void init(){sz = last = 0, rt = newnode(); }
    void reset(){last = 0; }
    void extend(int c){
        int np = newnode(len[last] + 1);
        int p;
        for(p = last; ~p && ch[p][c] == -1; p = link[p])ch[p][c] = np;
        if(p == -1)link[np] = rt;
        else{
            int q = ch[p][c];
            if(len[p] + 1 == len[q]) link[np] = q;
            else{
                int nq = newnode(len[p]+1);
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                link[nq] = link[q], link[q] = link[np] = nq;
                for(;~p && ch[p][c] == q; p = link[p]) ch[p][c] = nq;
            }
        }
        last = np;
    }
    void solve(int &l,int &r){
//        cout<
        int p = 0;
        int L = 0;
        int ans = -INF;
        int LL =strlen(s);
        for(int i = 0;s[i];i++){
            int c = s[i]-'a';
            if(ch[p][c]!=-1)p=ch[p][c],L++;
            else{
                while(p!=-1&&ch[p][c]==-1)p=link[p];
                if(p==-1){p=0;L=0;continue;}
                L = len[p]+1;
                p = ch[p][c];
            }
            if(L && ans < L-max(i-L+1,LL-i-1)){
                ans = L-max(i-L+1,LL-i-1);
                l = i-L+1, r = i;
            }
        }
    }
//两种写法都可以
/*    void solve(int &l,int &r){
        int p = 0;
        int L = 0;
        int ans = -INF;
        int LL =strlen(s);
        for(int i = 0;s[i];i++){
            int c = s[i]-'a';
            while(p&&ch[p][c]==-1)p=link[p];
            L = min(L,len[p]);
            if(ch[p][c] != -1){
                p = ch[p][c];
                L++;
            }
            if(L && ans < L-max(i-L+1,LL-i-1)){
                ans = L-max(i-L+1,LL-i-1);
                l = i-L+1, r = i;
            }
        }
    }*/
}SAM;

int main(){
    scanf("%s%s",s,t);
    SAM.init();
    for(int i=0;t[i];i++){
        SAM.extend(t[i]-'a');
    }
    int l,r;
    l=r=-1;
    SAM.solve(l,r);
    printf("%d %d\n",l,r);
    return 0;
}

你可能感兴趣的:(后缀自动机)