Time limit: 2.5 seconds
Memory limit: 768 mebibytes
- You are given two strings S = · · · and T = · · · 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 = · · · is the string S = · · · . 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 (, ) is lexicographically less than pair (, ) if either < , or = and < .
題意
- 在第一個串中找到一個子串同時屬於題目所給的兩個串的子串,同時價值要最大,價值是 子串的長度減去(第一個串的左邊界到該子串的左邊界和右邊界到該子串的右邊界的較大值)
題解
- 其實主要就是找到屬於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;
}