牛客寒假第六场 删除子序列
删除子序列
给出一个长度为nnn的字符串SSS和一个长度为mmm的不含重复字符的字符串TTT,每次你可以在SSS中删除一个等于TTT的子序列,最多可以删除多少次?
如字符串S=ababccdS=ababccdS=ababccd,T=abcT=abcT=abc,可以选择s1s2s5,s1s2s6,s1s4s5,s1s4s6,s3s4s5,s3s4s6s_1s_2s_5,s_1s_2s_6,s_1s_4s_5,s_1s_4s_6,s_3s_4s_5,s_3s_4s_6s1s2s5,s1s2s6,s1s4s5,s1s4s6,s3s4s5,s3s4s6进行删除,删除后分别得到abcd,abcd,bacd,bacd,abcd,abcdabcd,abcd,bacd,bacd,abcd,abcdabcd,abcd,bacd,bacd,abcd,abcd。
如果删除后得到abcdabcdabcd,则还可以再进行一次删除,最多可以删除222次。
题意:
在字符串中求定序的子序列的个数(不能重复)
思路:
我们可以一组一组的筛查
从t中最后一个字母开始,选一组,完成后继续选,
想到用stack这个数据结构,从t中的最后一个字符的栈开始遍历,必须满足(前一个的最后栈顶元素小于后一个的栈顶元素),在完成pop一组的情况下计数,若某次没有符合的元素了,就退出。
补充
怎么使用map呢???
可以用vector 代替stack
ve.emplace_back(),ve.pop_back(),ve.back()
AC代码
#include<bits/stdc++.h> using namespace std; const int N=1e6+1; int dp[N][27]; void solve() { int n,m; char s[N],t[27]; cin>>n>>m; scanf("%s",s+1); scanf("%s",t+1); stack<int>st[m+1]; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(s[i]==t[j]) { st[j].push(i); break; } } } int ans=0; while(1) { int t=n+1; //t是用来比较的初始位置!取最大,因为t中最后一个元素不需要满足什么条件 for(int i=m;i>=1;i--) { while(!st[i].empty()&&st[i].top()>t) st[i].pop(); if(st[i].empty()) {cout<<ans<<endl;return;} t=st[i].top(); st[i].pop(); } ans++; } } signed main() { int t; cin>>t; while(t--) solve(); }
本文作者:TimMCBen
本文链接:https://www.cnblogs.com/TimMCBen/p/15999721.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步