CodeForces 1231-E Middle-Out (思维 + 指针)

题目: 传送门
思路:
      我们从逆向的思维考虑,即每次将 T串的头部或尾部放到任意位置,使其成为 S串. 那么从贪心的角度想我们肯定希望每个数最多只进行一次交换,最终就能符合结果. 很明显 如果我们可以把T串分为三部分, 分别为 需要移动的部分,不需要移动的部分,需要移动的部分,不需要移动的部分肯定是 S串的子序列,这样他才能满足不需要移动就可以让最终结果满足.对于需要移动的部分,每次就只需要一步操作即能放到满足的位置.那么结果就是需要移动部分的长度。
      我们直接枚举不需要移动的部分的开头,每次用 26 个指针 扫一遍求得最长的子序列,然后去min即可.
记得特判不可能的情况
Ac_Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <stack>
#include <bitset>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#define fir first
#define sec second
using namespace std;


int n;
int h[30],p[30][110],lst[30];
int sz[30];
char s[110];
char t[110];

int main() {
	int q;
	scanf("%d",&q);
	while(q--) {
		memset(p,0,sizeof(p));
		memset(lst,0,sizeof(lst));
		memset(sz,0,sizeof(sz));
		scanf("%d",&n);
		scanf("%s%s",s,t);
		for(int i=0;i<n;i++) {
			int c = s[i] - 'a';
			p[c][lst[c]++] = i;
		}
		for(int i=0;i<n;i++) {
			sz[t[i]-'a']++;
		}
		int flag = 1;
		for(int i=0;i<26;i++) {
			if(sz[i] != lst[i]) flag = 0;
		}
		if(!flag) printf("-1\n");
		else {
			int ans = 500;
			for(int i=0;i<n;i++) {
				int now = i;
				int R= -1;
				memset(h,0,sizeof(h));
				while(true) {
					int c = t[now] -'a';
					while(h[c] < lst[c] && p[c][h[c]] <= R) h[c]++;
					if(h[c] >= lst[c]) break; 
					R = p[c][h[c]];
					now++;
					if(now == n) break;
				}
				ans = min(ans,n-now+i);
				// printf("%d %d\n", now,R);
			}
			printf("%d\n", ans);
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值