首先一看到这个题,由于是两个串,所以一定是第一步把两个串拼起来,然后中间加入一个非法字符。
然后我们考虑怎么算这个东西?
由于存在一个可以修改三次的设定。
那我们不妨直接先跑一遍
S
A
SA
SA,然后求出来各个数组。
直接枚举原串中的每一个后缀,然后暴力和后面的匹配。
令一个指针指到当前枚举的后缀,另一个指到第二串的开头,每次可以跳
l
c
p
lcp
lcp的长度,遇到一个不同的,就强行跳过。一共可以强行跳过三次。如果最后能整个跳完第二个串,就
a
n
s
+
+
ans++
ans++
然后我们可以通过 r m q rmq rmq在 n l o g n nlogn nlogn预处理之后, O ( 1 ) O(1) O(1)计算 l c p lcp lcp。
感觉还是有一些细节需要看代码才行。
然后这个题就解决了!
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk make_pair
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 4e5+1e2;
int wb[maxn],sa[maxn];
int rk[maxn],tmp[maxn];
int n,m;
int h[maxn],height[maxn];
char s[maxn],s1[maxn];
char a[maxn];
int len,len1;
int t;
int f[maxn][21];
void getsa()
{ int *x=rk,*y=tmp;
int s=128;
int p=0;
for (int i=1;i<=n;i++) x[i]=a[i],y[i]=i;
for (int i=1;i<=s;i++) wb[i]=0;
for (int i=1;i<=n;i++) wb[x[y[i]]]++;
for (int i=1;i<=s;i++) wb[i]+=wb[i-1];
for (int i=n;i>=1;i--) sa[wb[x[y[i]]]--]=y[i];
for (int j=1;p<n;j<<=1)
{ p=0;
for (int i=n-j+1;i<=n;i++) y[++p]=i;
for (int i=1;i<=n;i++) if (sa[i]>j) y[++p]=sa[i]-j;
for (int i=1;i<=s;i++) wb[i]=0;
for (int i=1;i<=n;i++) wb[x[y[i]]]++;
for (int i=1;i<=s;i++) wb[i]+=wb[i-1];
for (int i=n;i>=1;i--) sa[wb[x[y[i]]]--]=y[i];
swap(x,y);
p=1;
x[sa[1]]=1;
for (int i=2;i<=n;i++)
x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+j]==y[sa[i-1]+j]) ? p : ++p;
s=p;
}
for (int i=1;i<=n;i++) rk[sa[i]]=i;
h[0]=0;
for (int i=1;i<=n;i++)
{
h[i]=max(h[i-1]-1,0);
while (i+h[i]<=n && sa[rk[i]-1]+h[i]<=n && a[i+h[i]]==a[sa[rk[i]-1]+h[i]]) h[i]++;
}
for (int i=1;i<=n;i++) height[i]=h[sa[i]];
}
int query(int l,int r)
{
int k = log2(r-l+1);
return min(f[l][k],f[r-(1<<k)+1][k]);
}
void init()
{
memset(wb,0,sizeof(wb));
memset(sa,0,sizeof(sa));
memset(rk,0,sizeof(rk));
memset(h,0,sizeof(h));
memset(height,0,sizeof(height));
memset(tmp,0,sizeof(tmp));
memset(f,127/3,sizeof(f));
}
int getlcp(int x,int y)
{
if (rk[x]>rk[y]) swap(x,y);
return query(rk[x]+1,rk[y]);
}
bool check(int now)
{
if(len-now+1<len1) return false;
int rest=3;
int rev=len+2;
int x = getlcp(now,rev);
rev+=x;
now+=x;
rest--;
if(rev>n) return true;
rev++;
now++;
if(rev>n) return true;
x = getlcp(now,rev);
rev+=x;
now+=x;
rest--;
if(rev>n) return true;
rev++;
now++;
if(rev>n) return true;
x=getlcp(now,rev);
rev+=x;
now+=x;
rest--;
if(rev>n) return true;
rev++;
now++;
if(rev>n) return true;
x=getlcp(now,rev);
rev+=x;
if (rev<=n) return false;
else return true;
}
int main()
{
cin>>t;
while (t--)
{
init();
scanf("%s",s+1);
len = strlen(s+1);
scanf("%s",s1+1);
len1 = strlen(s1+1);
n=0;
int ans=0;
for (int i=1;i<=len;i++) a[++n]=s[i];
a[++n]='*';
for (int i=1;i<=len1;i++) a[++n]=s1[i];
getsa();
for (int i=1;i<=n;i++) f[i][0]=height[i];
for (int j=1;j<=20;j++)
for (int i=1;i<=n;i++)
if(i+(1<<j)-1<=n)
{
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
for (int i=1;i<=len;i++)
if(check(i)) ans++;
cout<<ans<<"\n";
}
return 0;
}