题目:
题意:
给出两个字符串,在 A A A串中至多修改一个字符,问这样之后其在 B B B串匹配子序列的最大长度是多少
分析:
我不想跟你多说话,并向你随手扔了个
n
2
n^2
n2暴力
.
.
.
...
...
然后就
A
A
A了,哈哈哈
想得美呢,虽然也差不多。好了,让我们回到正题,
n
2
n^2
n2的暴力可能肯定是过不去,那让我们考虑下如何优化,我想到的是因为在逐字匹配的时候如果遇上了连续相同的字符,我们完全可以省略这一段的匹配,直接跳到第一个不相同的字符
设
g
1
g_1
g1表示
A
A
A串每个相同的字符要加上多少位就能到达第一个不同的字符,如
A
:
a
a
a
b
b
c
A:aaabbc
A:aaabbc,那么
g
1
:
321211
g_1:321211
g1:321211。
g
2
g_2
g2表示
B
B
B串中的,在匹配的过程中,一旦遇上了相同的,我们便可以跳到
m
i
n
(
g
1
,
g
2
)
min(g_1,g_2)
min(g1,g2)
代码:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define LL long long
#define LZX IMS
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
char s1[50005],s2[50005];
int g1[50005],g2[50005];
int main()
{
memset(g1,0x3f,sizeof(g1));memset(g2,0x3f,sizeof(g2));
scanf("%s",s1+1);scanf("%s",s2+1);
int l2=strlen(s2+1),l1=strlen(s1+1);
g1[l1]=1;
for(int i=l1-1;i;i--)
if(s1[i]==s1[i+1]) g1[i]=g1[i+1]+1;
else g1[i]=1;
g2[l2]=1;
for(int i=l2-1;i;i--)
if(s2[i]==s2[i+1]) g2[i]=g2[i+1]+1;
else g2[i]=1;
int ans=0,tf,cnt,k,j;
for(int i=1;i<=l2;i++)
{
if(ans==l1) break;
tf=0;cnt=0;k=i;j=1;
for(;j<=l1&&k<=l2;)
{
if(s1[j]==s2[k])
{
int giao=min(g1[j],g2[k]);
j+=giao;k+=giao;
cnt+=giao;
continue;
}
if(s1[j]!=s2[k]&&tf) break;
if(s1[j]!=s2[k]&&!tf) tf=1,cnt++,j++,k++;
}
ans=max(ans,cnt);
}
cout<<ans;
return 0;
}