题意:
我们把某个字符串t1t2t3...tn-1tn的左循环移位称为字符串t2t3...tn-1tnt1。
类似地,我们把字符串t的右循环移动称为字符串tnt1t2t3...tn-1。
如果字符串t的左循环移位等于其右循环移位,我们就说它是好的。
给你一个由数字0-9组成的字符串s。
你需要从s中擦除多少个字符才能使其成为好字符串?
输入
第一行包含单个整数t(1≤t≤1000)--测试案例的数量。
接下来的t行包含测试用例--每行一个。每个测试用例的第一行也是唯一一行包含字符串s(2≤|s|≤2⋅105)。每个字符si是数字0-9。
保证字符串的总长度不超过2⋅105。
输出
对于每个测试案例,打印你需要从s中删除的最小字符数,以使其成为好的。
题解:
假设我们设这个字符串为奇数,长度为5
原
1 2 3 4 5
2 3 4 5 1
5 1 2 3 4
2 = 5
3 = 1
4 = 2
5 = 3
1 = 4
我们发现如果长度为奇数,只有所有字母相同的情况下才会出现
接着我们考虑偶数的情况
1 2 3 4
2 3 4 1
4 1 2 3
2 = 4
3 = 1
4 = 2
1 = 3
发现只有下标为偶数时都相等,为奇数时都相等才行;
为偶数时会有两种不同数字(相同的奇数n为奇数已经考虑了)
那么我们暴力枚举所有(奇数位,偶数位)为两种数字的情况
时间复杂度为9*9*2e5发现可以过
#include<iostream>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
int n;
char a[200050];
int len1(int x,int y)
{
char o = x+'0';
char p = y+'0';
int f = 0;
int cnt = 0;
for(int i = 1;i <= n;i++)
{
if(a[i]==o&&f == 0)
{
f^=1;
}
if(a[i]==p&&f == 1)
{
f^= 1;
cnt += 2;
}
}
return cnt;
}
void solve()
{
cin >> a+1;
n = strlen(a+1);
map<int,int> vis;
int ans = 0;
for(int i = 1;i <= n;i++)
{
vis[a[i]-'0']++;
ans = max(ans,vis[a[i]-'0']);
}
for(int i = 0;i <= 9;i++)
{
for(int j = 0;j <= 9;j++)
{
if(i == j)
continue;
ans = max(ans,len1(i,j));
}
}
cout<<n-ans<<"\n";
}
int main()
{
int t;
cin >> t;
while(t--)
{
solve();
}
}