CF1654B solution

Problem

给定字符串 \(s\),每次删除最大前缀 \(a\) 满足删除后的 \(s\) 不包含 \(a\),问最终的 \(|s|\)

link->https://codeforces.com/contest/1654/problem/B

Solution

其实只需要每次删除 \(s\) 的首字符即可直至不满足条件即可。

为什么呢?首先假定 \(a\) 为满足条件的最大前缀,那么有 \(3\) 种情况:

  • \(|a|\ge 2\)\(a\) 肯定满足其任意一个字符均在删除后的 \(s\) 中出现过(若满足也不一定符合条件)。

  • \(|a|=1\)。此时 \(a\)\(s\) 的第一个字符。

  • \(|a|=0\)。此时无法继续删除。

可以看到,如果我们采用每次删除 \(s\) 首字符的情况那么一定满足后两者的情况。那么第一种呢?可以看见,可以删除 \(s\) 的首字符是 \(a\) 满足条件的必须情况,也就是说,如果可以删除 \(a\) 那么就一定满足可以删除 \(s\) 的第一个字符,如果不满足,那么 \(s\) 将的长度将缩小,直至满足情况为止,将变成第二或第一种的情况。

我们也可以使用数学归纳法,将话说的标准一点:

  • \(|a|=0\) 时满足条件;

  • \(|a|=1\) 时满足条件;

  • \(|a|-1\) 满足条件时,那么删除除 \(a\) 的最后一个字符外的所有字符,如果可以继续删除则继续删除,反之不可以删除,停止删除。满足条件。

  • 对于每一个 \(|a|\) 都满足条件,证毕。

至于判断是否可以删除首字母,我们可以采用桶排解决。

Code

#include<bits/stdc++.h>
#define pd push_back
#define pb pop_back
#define mk make_pair
//#define int long long
#define PII pair<int,int>
#define _for(a,b,c) for(int a=b;a<=c;a++)
#define _rep(a,b,c) for(int a=b;a>=c;a--)
using namespace std;
template <typename T> inline void read(T& x) {
	x=0; T f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch&15); ch=getchar(); }
	x=x*f;
	return;
}
template <typename T,typename ...Arg> inline void read(T& x,Arg& ...arg){
	read(x); read(arg...);
}
int power(int a,int b) { 
	int ans=1;
	do {
		if(b&1) ans*=a; a*=a;
	} while(b>>=1);
	return ans;
}
int T,cnt[128];
signed main() {
	read(T);
	while(T--) {
		memset(cnt,0,sizeof(cnt));
		string s;
		cin>>s;
		_for(i,0,s.size()-1)
			++cnt[s[i]];
		int k=-1;
		_for(i,0,s.size()-1)
			if(cnt[s[i]]>1)
				--cnt[s[i]],k=i;
			else
				break;
		_for(i,k+1,s.size()-1)
			putchar(s[i]);
		puts("");
	}
	return 0;
}
posted @ 2022-08-01 14:18  lsj2009  阅读(26)  评论(0)    收藏  举报