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<<link[0]<<endl;
        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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值