1 条题解
-
0
算法一
匹配模拟+顺路统计 但是实现起来还是比较有难度,具体都在代码注释里面了
代码
#include<bits/stdc++.h> #define int long long #define inf 0x3f3f3f3f3f3f3f3f #define For(i,a,b) for(int i=(a);i<=(b);i++) #define foR(i,a,b) for(int i=(a);i>=(b);i--) using namespace std; const int N=2e5+5; char s[N],t[N]; signed main() { scanf(" %s",s); scanf(" %s",t); int n=strlen(s),m=strlen(t); vector<int> rnk(m);//能保证右侧匹配的最右边的s的下标 foR(i,m-1,0) { int pos=n-1; if(i<m-1) pos=rnk[i+1]-1;//把上一个位置匹配的结果迭代过来 while(s[pos]!=t[i]) --pos;//不匹配就往前找到,找到的结果是最后一个匹配的位置 rnk[i]=pos;//根据上述定义更新rnk就行了 } int ans=0; int pos=0;//匹配到的长度 For(i,0,n-1) { int rpos=n-1;//最右侧能更新到的位置(初始化考虑的是如样例1取到最优解的情况) if(pos<m) rpos=rnk[pos]-1;//当前不是匹配最后一位,但是已经匹配到某个值,那后面的同样的字母位置都可以删除了 //匹配最后一位的时候我们考虑的是如样例1的情况,从结尾删除 ans=max(ans,rpos-i+1); if(pos<m&&t[pos]==s[i]) ++pos;//可以就继续匹配下去 } cout<<ans; return 0; }算法二
和算法一类似,但是我个人觉得比较好懂、好写,写起来就像单调栈计算最大区块面积最后一步的统计一样(可能是dp写多的缘故)
一样的思路,复制了两遍: pre[i]表示前面 t 到 i ,s到pre[i]时可以匹配,suf反过来定义相同,最后走一个尺取法就可以了
代码
#include<bits/stdc++.h> #define int long long #define inf 0x3f3f3f3f3f3f3f3f #define For(i,a,b) for(int i=(a);i<=(b);i++) #define foR(i,a,b) for(int i=(a);i>=(b);i--) using namespace std; const int N=2e5+5; char s[N],t[N]; int pre[N],suf[N]; signed main() { scanf(" %s",s); scanf(" %s",t); int n=strlen(s),m=strlen(t); int j=0; For(i,0,n-1) { if(j<m&&s[i]==t[j]) ++j; pre[i]=j; } j=m-1; foR(i,n-1,0) { if(j>=0&&s[i]==t[j]) --j; suf[i]=j; } suf[n]=m-1; int ans=0; int r=0; int tmp=0; For(l,0,n) { while(r<=n&&tmp>=suf[r]+1) ++r; ans=max(ans,r-l-1); tmp=pre[l]; } cout<<ans; return 0; }
- 1
信息
- ID
- 10
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者