翻译
给你一个长度为 (n) ( (n le2 imes 10^5) ) 的只包含数字字符的串 (t) ,请你删除一些的字符,使得将第一个字符移动到末尾得到的串和将最后一个字符移动到开头得到的串相等。
求出最少要删除多少个字符。
思路
先观察满足上述条件的字符串有什么特点,分类讨论下:
-
当一个串的长度为偶数时:
假设我们有一个长度为 (6) 的字符串 (A) :
那么将第一个字符移动到末尾得到的串和将最后一个字符移动到开头得到的串以及他们的相等关系就是:
那么把这些相等关系整理出来就是:
(A_6=A_2=A_4=A_6)
(A_1=A_3=A_5=A_1)
显然,奇数位置上的字符都相等,偶数位置上的字符也都相等。
所以我们得出结论 1 :当一个满足条件串的串长为为偶数时,那么这个串一定是 (ababab...) 的形式。
-
当一个串的长度为奇数时:
假设我们有一个长度为 (7) 的字符串 (A) :
那么将第一个字符移动到末尾得到的串和将最后一个字符移动到开头得到的串以及他们的相等关系就是:
那么把这些相等关系整理出来就是:
(A_7=A_2=A_4=A_6=A_1=A_3=A_5=A_7)
显然,所有位置上的字符都相等。
所以我们得出结论 2 :当一个满足条件串的串长为为奇数时,那么这个串一定是 (aaaaaa...) 的形式。
综上,我们只要找到一个最长的子串,使得这个串为 (ababab...) 的形式且长度为偶数 或者 (aaaaaa...) 且长度为奇数。
因为字符串仅有数字字符构成,所以我们可以直接枚举 (a) 和 (b),然后贪心地取最大,最后用总长减去能取出的最长的子串即可。
Code
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<bitset>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
int read()
{
int ans=0,f=1;
char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
return ans*f;
}
const int N=2e5+5;
int t,n,ans;
char s[N];
int main()
{
t=read();
while(t--)
{
ans=0;
scanf("%s",s+1);
n=strlen(s+1);
for(int a=0;a<=9;++a)
for(int b=0;b<=9;++b)
//枚举a和b
{
int tmp=0;
//tmp为已经取出来的长度
for(int i=1;i<=n;++i)
if(tmp%2==0&&s[i]-'0'==a||tmp%2==1&&s[i]-'0'==b)
//贪心取
tmp++;
if(tmp%2==1&&a!=b)
//如果取出的长度为奇数,那么只有a=b才合法,否则只能变成偶数
tmp--;
ans=max(ans,tmp);
}
//用总长减去最长能取出的长度就是最少删去字符的数量
printf("%d
",n-ans);
}
return 0;
}