22上海市赛 - E. Expenditure Reduction(预处理)

题意
给定长度分别为 n,m 的两个字符串 A,B,保证 B串 为 A串 的子序列。
可以删掉串 A 的一段前缀,一段后缀。
问,仍然满足 B串 为 A串 的子序列的条件下,A串 的长度最小为多少?输出一个满足的串。

1 ≤ ∣ A ∣ ≤ 5 ∗ 1 0 5 , 1 ≤ ∣ B ∣ ≤ 100 1\leq |A| \leq 5*10 ^ 5, 1 \leq |B| \leq 100 1A5105,1B100
串中只包含小写字母和数字。

思路
就是要找一段连续的区间,满足 B串 中的所有字符都按顺序出现过。

场上是这样想的,把每个字符所在的位置都存下来,B串的长度只有100,所以可以遍历第一个字符所在位置 pos,然后对于B串后面的位置,每次找到其在A串中 pos 位置后面第一次出现的位置,将 pos 更新成该位置,直到最后一个字符。这样对于最前端确定的情况下,使得最后端尽可能靠前,取所有情况中的长度差的最小值。
保证了正确性,但是复杂度估计错了,字符串长度 5e5,100个字符,每次二分找,时间复杂度是 O ( 5 e 5 ∗ 100 ∗ 20 = 1 e 9 ) O(5e5*100*20 = 1e9) O(5e510020=1e9)。。当时算复杂度的时候没看多组数据。。

而每次都二分找某个字符在某个位置后面第一次出现的位置,其实可以把这个预处理出来。

字符串长度是 5e5,一共只有 36 种字符,从后往前记录下每个位置后面每个字符首次出现的位置 ne[i, j]

后面只需要找 B串 首个字符出现的位置,然后跳到这个位置后面第二个字符首次出现的位置,直到最后一个字符。然后这段区间就确定了,取所有区间长度的最小值。复杂度O(n*m)。

#include<bits/stdc++.h>
using namespace std;

#define Ios ios::sync_with_stdio(false),cin.tie(0)

const int N = 200010, mod = 1e9+7;
int T, n, m;
char a[N], b[N];
int ne[N][40];

int getnum(char c)
{
	if(c >= 'a' && c <= 'z') return c - 'a' + 1;
	else return c - '0' + 27;
}

void init()
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<40;j++)
			ne[i][j] = 0;
}

signed main(){
	Ios;
	cin >> T;
	while(T--)
	{
		cin >> a + 1 >> b + 1;
		n = strlen(a + 1);
		m = strlen(b + 1);
		
		init();
		
		for(int i=n-1;i>=1;i--)
		{
			for(int j=1;j<40;j++) ne[i][j] = ne[i+1][j];
			ne[i][getnum(a[i+1])] = i + 1;
		}
		
		int mina = 1e9, pos;
		for(int i=1;i<=n;i++)
		{
			if(a[i] != b[1]) continue;
			int now = i;
			
			int flag = 1;
			for(int j=2;j<=m;j++)
			{
				if(ne[now][getnum(b[j])]) now = ne[now][getnum(b[j])];
				else flag = 0;
			}
			if(!flag) continue;
			if(now - i + 1 < mina){
				mina = now - i + 1;
				pos = i;
			}
		}
		for(int i=pos;i<=pos+mina-1;i++) cout << a[i];
		cout << endl;
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值