首页 > 其他 > 详细

CF ECR92 C. Good String

时间:2020-07-30 19:16:09      阅读:70      评论:0      收藏:0      [点我收藏+]

CF ECR92 C. Good String

技术分享图片

题目链接

CF ECR92 C. Good String

题目概述

题目中定义了字符串\(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.输出需要删减的最小的字符串的数量.输入数据的规模:

\[1 \leq t \leq 1000, 2 \leq |s| \leq 2 \cdot 10^5 \]

思路

根据上面那个Good String的定义,可以得到对于一个Good String\(b_1b_2\cdots b_k\),只可能存在以下两种情况:

  1. \(b_1=b_2=\cdots=b_k\)
  2. \(b_1=b_3=\cdots=b_{k-1},b_2=b_3=b_4\cdots=b_k, b_1 != b_2,k\%2=0\)
    从上面的定义代换可以得到,这里简单说一说为什么\(k\%2=0\)时奇偶位上的数字都相同才是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的长度.用字符串总长度减去这个长度得到的就是要删减的字符的数量.

其它

CF ECR92 C. Good String

原文:https://www.cnblogs.com/2018slgys/p/13405065.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!