题目大意
题目分析
Algorithm Alpha
将母串分成许多个块,每个块内所有位置都可以互相调换。
那么一个字符串能成功匹配一个块当且仅当其每个字母出现次数都不比块内该字母出现次数多。
我们处理
fi,j
,表示从匹配串第
i
个位置开始,匹配从第
利用这三个数组,我们就可以扫一遍做答案了。
时间复杂度
Algorithm Beta
听说在基础
LCS
的
dp
上稍作改动即可得到这题简便解法,代码复杂度极低。我没有仔细思考,就交给感兴趣的读者脑补了。
时间复杂度
O(n2)
。
代码实现
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cctype>
#include <cmath>
using namespace std;
int read()
{
int x=0,f=1;
char ch=getchar();
while (!isdigit(ch))
{
if (ch=='-')
f=-1;
ch=getchar();
}
while (isdigit(ch))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int N=2050;
const int Q=100050+N;
const int C=26;
struct Query
{
int l,r;
}qs[Q];
bool operator<(Query a,Query b)
{
return a.l<b.l||a.l==b.l&&a.r<b.r;
}
int f[N][N],g[N][N],pre[N][N],suc[N][N];
int cnt[N][C],app[N][C];
int len[N],st[N],en[N];
int n,m,q,tot,ans;
char S[N],T[N];
void calc()
{
int wrg[N];
memset(app,0,sizeof app);
memset(wrg,0,sizeof wrg);
for (int i=m-1;i>=0;i--)
for (int j=0;j<tot;j++)
{
int c=T[i]-'a';
if (app[j][c]++==cnt[j][c]) wrg[j]++;
if (i+len[j]<m)
{
c=T[i+len[j]]-'a';
if (--app[j][c]==cnt[j][c]) wrg[j]--;
}
if (i+len[j]>m) continue;
if (!wrg[j])
f[i][j]=f[i+len[j]][j+1]+len[j],g[i][j]=g[i+len[j]][j+1]+1;
}
memset(app,0,sizeof app);
for (int i=0;i<tot;i++) wrg[i]=-1;
for (int i=0;i<m;i++)
for (int j=0;j<tot;j++)
{
int c=T[i]-'a';
if (app[j][c]++==cnt[j][c])
{
while (T[wrg[j]+1]!=T[i])
c=T[++wrg[j]]-'a',app[j][c]--;
c=T[++wrg[j]]-'a',app[j][c]--;
}
pre[i][j]=i-wrg[j];
}
memset(app,0,sizeof app);
for (int i=0;i<tot;i++) wrg[i]=m;
for (int i=m-1;i>=0;i--)
for (int j=0;j<tot;j++)
{
int c=T[i]-'a';
if (app[j][c]++==cnt[j][c])
{
while (T[wrg[j]-1]!=T[i])
c=T[--wrg[j]]-'a',app[j][c]--;
c=T[--wrg[j]]-'a',app[j][c]--;
}
suc[i][j]=wrg[j]-i;
}
}
void getans()
{
ans=0;
for (int i=0;i<m;i++)
for (int j=0;j<tot;j++)
{
int tmp=f[i][j],h=g[i][j];
if (i&&j) tmp+=pre[i-1][j-1];
tmp+=suc[i+f[i][j]][j+h];
ans=max(ans,tmp);
}
}
int main()
{
freopen("lcs.in","r",stdin);
freopen("lcs.out","w",stdout);
scanf("%s",T),m=strlen(T);
scanf("%s",S),n=strlen(S);
q=read();
for (int i=1;i<=q;i++)
qs[i].l=read(),qs[i].r=read();
for (int i=0;i<n;i++)
qs[++q].l=i,qs[q].r=i;
sort(qs+1,qs+1+q);
tot=0;
int lc=qs[1].l,rc=qs[1].r;
for (int i=2;i<=q;i++)
{
if (qs[i].l>rc)
{
st[tot]=lc,en[tot]=rc;
len[tot++]=rc-lc+1;
lc=qs[i].l,rc=0;
}
rc=max(qs[i].r,rc);
}
st[tot]=lc,en[tot]=rc;
len[tot++]=rc-lc+1;
for (int i=0;i<tot;i++)
for (int j=st[i];j<=en[i];j++)
cnt[i][S[j]-'a']++;
calc();
getans();
printf("%d\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}