目的是为了达到字符串中所有字母相同,那么最后字符串中一定仅仅剩下一个字母。
我们的删除操作是什么呢?
是隔一个位置删除,直到不能删除为止。
那么怎么进行这样的删除呢?很容易想到通过一个f的变化,每删除一次就变化f,f=0删除,f=1不删除,每一次更新,就能实现隔一个位置进行删除的操作。
那么如何知道一个字母是否被删除呢?
我们可以通过建立一个flag标记数组,flag=1为没被删除,否则被删除。
如何知道一个字符串已经被删除干净呢?
我们想到了遍历这个字符串,看是否都是相同值,也有其他办法比如看看她是否还更新。
#include<iostream>
#include<cstring>
using namespace std;
int t;
bool flag[200010];
int main()
{
cin>>t;
while(t--)
{
string s;
cin>>s;
int minn=1e9;
for(char c='a';c<='z';c++)
{
int cnt=0;
memset(flag,1,sizeof(flag));
while(1)
{
bool f=1;
for(int i=0;i<s.size();i++)
if(flag[i]&&s[i]!=c)f=0;
if(f)break;
cnt++;
f=0;
for(int i=0;i<s.size();i++)
{
if(!f&&s[i]!=c&&flag[i])flag[i]=0,f=1;
else if(flag[i])f=0;
}
}
minn=min(minn,cnt);
}
cout<<minn<<endl;
}
return 0;
}
但是这样毫不留情TLE了,让我们来思考复杂度更加优秀的算法。
我们可以考虑遍历保留哪个字符,那么在字符间隔内的这一段区间内,所有字母都应该被删除,这也就导致了我们必须想办法算出怎么才能将这些次数计算出来。
看字符串的删除方式,每一次都是隔位删除,这也就导致了我们每次的字符串都是长度除以2且向下取整,这就得到了一个对数地计算方法,如果要将字符串长度变为1则需要log2x次,如果删除干净,需要log2x+1次。
让我们来看一看代码吧,应该解释地很清楚了。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
string s;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--)
{
cin>>s;
int ans=1e9;
for(int c='a';c<='z';c++)
{
int res=0,len=0;
for(int i=0;i<s.size();i++)
if(s[i]!=c) len++;
else res=max(res,len),len=0;
res=max(res,len);
if(res==0) {ans=0;break;}
ans=min(ans,(int)log2(res)+1);
}
cout<<ans<<'\n';
}
}