题目链接
题意:给出一个字符串,然后有q次询问,在字符串中找出最短的字串使其包涵询问的2个串。
询问的串长度不大于4,暴力预处理一下,每个长度的子串在原串中的位置。然后在暴力计算,这里暴力计算也是有技巧的,因为预处理的数组是有序的所以这里暴力要使用线性的方法,具体是正着先找小于的,逆着找大于的。每次不要从头开始,因为有序,直接继续。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<set>
#include<map>
#include<string>
#include<cassert>
using namespace std;
#define cl(a,b) memset(a,b,sizeof(a))
#define fastIO ios::sync_with_stdio(false);cin.tie(0);
#define LL unsigned long long
#define pb push_back
#define gcd __gcd
#define For(i,j,k) for(int i=(j);i<=k;i++)
#define lowbit(i) (i&(-i))
#define _(x) printf("%d\n",x)
typedef vector<LL> vec;
typedef pair<int,int> PI;
const double EPS = 1e-8;
const int maxn = 2e6+10;
const int inf = 1 << 28;
int n,m,x;
int p = 31;
char str[maxn/10];
char s[2][maxn];
vector<int> v[maxn];
map<pair<int,int>,int> mp;
int main(){
scanf("%s",str);
int len = strlen(str);
for(int i=1;i<=4;i++){
for(int j=0;j+i-1<len;j++){
int t=0;
for(int k=j;k<i+j;k++){
t=t*p+(str[k]-'a')+11;
}
v[t].pb(j);
}
}
int q;scanf("%d",&q);
while(q--){
scanf("%s%s",&s[0],&s[1]);
int t1=0,t2=0;
int n=strlen(s[0]),m=strlen(s[1]);
for(int i=0;i<n;i++)t1=t1*p+(s[0][i]-'a')+11;
for(int i=0;i<m;i++)t2=t2*p+(s[1][i]-'a')+11;
if(mp[make_pair(t1,t2)]!=0){
printf("%d\n",mp[make_pair(t1,t2)]);
continue;
}
int ans=1<<27;
//线性的暴力查找!
for(int i=0,j=0;i<v[t1].size();i++){
while(j<v[t2].size()&&v[t2][j]<v[t1][i])j++;
if(j>=v[t2].size())break;
ans = min(ans, max(v[t1][i]+n,v[t2][j]+m)-min(v[t1][i],v[t2][j]));
}
for(int i=v[t1].size()-1,j=v[t2].size()-1;i>=0;i--){
while(j>=0&&v[t2][j]>v[t1][i])j--;
if(j<0)break;
ans = min(ans, max(v[t1][i]+n,v[t2][j]+m)-min(v[t1][i],v[t2][j]));
}
if(ans == (1<<27))ans=-1;
mp[make_pair(t1,t2)]=ans;
mp[make_pair(t2,t1)]=ans;
printf("%d\n",ans);
}
return 0;
}