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;
}