牛客寒假第六场 删除子序列

删除子序列

给出一个长度为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();
}
posted @ 2022-03-13 10:30  TimMCBen  阅读(98)  评论(0)    收藏  举报