大致题意:在第一个字符串str1中找一个最长的子序列,要求这个子序列的字典序严格大于第二个字符串。
题解上面说的是维护一下以当前位置的字符结尾的 满足的子序列 的最长长度,感觉说起来好奇怪。反正不知道因为什么原因,在比赛的时候就是没有想到这种写法,但是看完题的第一眼,直觉告诉我应该用线段树。所以二话不说上手写一发,然后wa了。。最后手写了几组数据,把细节处理了就A了。主要是这两组数据aaaaa aaa 和aaaaa aaaaa。处理出这两种情况之后就A了。
最后,代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+100;
char str1[maxn];
char str2[maxn];
int tree[maxn<<2];
int ans;
void push_up(int x,int tp)
{
tree[x]=max(tree[tp],tree[tp+1]);
}
void build(int l,int r,int x)
{
if(l==r)
{
tree[x]=str1[l]-'a';
return ;
}
int tp=x<<1;
int mid=l+r>>1;
build(l,mid,tp);
build(mid+1,r,tp+1);
push_up(x,tp);
}
void query(int l,int r,int L,int x,int k)
{
if(r<L||ans||tree[x]<k)
return ;
if(l==r)
{
ans=l;
return ;
}
int tp=x<<1;
int mid=l+r>>1;
query(l,mid,L,tp,k);
query(mid+1,r,L,tp+1,k);
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
scanf("%s %s",str1+1,str2);
build(1,n,1);
int l=0;
int Accepty=-1;
for(int i=0;i<m;++i)
{
ans=0;
query(1,n,l,1,str2[i]-'a'+1);
if(ans)
{
Accepty=max(Accepty,n-ans+1+i);
}
ans=0;
query(1,n,l,1,str2[i]-'a');
if(ans)
{
l=ans+1;
if(i==m-1&&ans!=n)
{
Accepty=max(Accepty,n-ans+1+i);
}
}
else
break;
}
cout<<Accepty<<endl;
return 0;
}