
题目中定义了字符串\(a_1a_2\dots a_n\)的左旋转\(a_2a_3\dots a_na_1\)和右旋转\(a_na_1a_2\dots a_{n-1}\),然后定义了一个Good String的东西,左旋转和右旋转是同一个字符串,即\(a_2a_3\dots a_na_1=a_na_1a_2\dots a_{n-1}\),现在给定一个字符串,计算这个字符串经过删减后可以得到一个Good String需要删减的最小的字符的数量.输入的输入格式为,先输入一个整数T,表示测试的数量,然后输入T个连续的仅由0~9构成的字符串s.输出需要删减的最小的字符串的数量.输入数据的规模:
根据上面那个Good String的定义,可以得到对于一个Good String\(b_1b_2\cdots b_k\),只可能存在以下两种情况:
Good String,对于一个Good String\(xyxy\cdots xy\)来说,左旋转之后得到的是\(yxy\cdots xyx\),有旋转之后得到是\(yxyxy\cdots x\)旋转实际上是把原来奇偶位上的数字进行了一个简单的变换,原来奇数位的数字变成偶数位的,偶数位的变成奇数位的.如果不满足\(k%2=0\)的话,\(xyxy\cdots xyx\),左旋转之后是\(yxy\cdots xyxx\),二右旋转则是\(xxyxy\cdots xy\),这样的两个字符串就不相等了.所以可以先从\(a_1a_2\cdots a_n\)中计算满足上面任意一个Good String条件可以得到的最长Good String的长度,然后用字符串总长减去这个最长的Good String的长度得到的就是需要删除的最少的字符的数量.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+5;
const int M = 10;
int buf[N];
int count_one(size_t n, int v){
int ans = 0;
for(auto i = 0; i < n; ++i){
if(buf[i] == v){
++ans;
}
}
return ans;
}
int count_two(size_t n, int x, int y){
int ans = 0;
for(auto i = 0; i < n; ++i){
if( ans & 1){
// 上一个x后面出现的y
if(buf[i] == y){
++ans;
}
}else{
// 最初的x或者上一个y后面的x
if(buf[i] == x){
++ans;
}
}
}
// 最后得到的ans是xyxy...(xy)的个数,可能存在末尾是单独一个x的情况
if( ans & 1)
--ans;
return ans;
}
void solve(size_t n){
int ans = 0;
// 计算xxx出现的次数
for(int i = 0; i < M; ++i){
ans = max(ans, count_one(n, i));
}
// 计算xyxy...出现的次数,两者取最大值
for(int i = 0; i < M; ++i){
for(int j = 0; j < M; ++j){
if( i != j){
ans = max(ans, count_two(n,i,j));
}
}
}
// 最后的ans就是所谓的good string的最大长度,n-ans就是应该去掉的部分的长度
cout<<(n-ans)<<endl;
}
int main(int argc, const char** argv) {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin>>t;
while(t--){
string s;
cin>>s;
for(auto i = 0; i < s.size(); i++){
buf[i] = s[i]-‘0‘;
}
solve(s.size());
}
return 0;
}
通过count_one计算从字符串可以提取出\(xxx\cdots x\)这种Good string的长度,然后取其中长度的最大值;通过count_two计算出从字符串中提取出\(xyxy\cdots xy\)这种Good String的字符串的长度,在扫描原来字符串是,用ans记录这个拟Good String的长度(如果最后的ans是奇数要减一,对应末尾多一个x的情况,末尾不会多余y,因为y一定是和x配对的.在第二种情况下,要关注前面一个字符的类型,比如如果前面统计的是x,那么只有遇到y才会扩大Good String的长度,同时更改关注的字符为y,这样当下一轮遇到x时才统计扩大Good string的长度,这里面是通过ans的奇偶性来实现的,当ans是偶数时表示期待下一个字符是x,当ans是奇数时表示期待下一个字符是y.扫描完毕后,有可能找到的拟Good String末尾多余一个x,此时需要丢弃这个x得到的才是Good String.枚举所有的数字字符可能的组合类型(两个数字字符此时不能相同),从中计算得到的Good String的最大值,和上面第一种情况的最大值再去最大值,得到的就是可以得到的最长的Good String的长度.用字符串总长度减去这个长度得到的就是要删减的字符的数量.
原文:https://www.cnblogs.com/2018slgys/p/13405065.html