zoukankan      html  css  js  c++  java
  • CF ECR92 C. Good String

    CF ECR92 C. Good String

    博客图片

    题目链接

    CF ECR92 C. Good String

    题目概述

    题目中定义了字符串(a_1a_2dots a_n)的左旋转(a_2a_3dots a_na_1)和右旋转(a_na_1a_2dots a_{n-1}),然后定义了一个Good String的东西,左旋转和右旋转是同一个字符串,即(a_2a_3dots a_na_1=a_na_1a_2dots 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_2cdots b_k),只可能存在以下两种情况:

    1. (b_1=b_2=cdots=b_k)
    2. (b_1=b_3=cdots=b_{k-1},b_2=b_3=b_4cdots=b_k, b_1 != b_2,k\%2=0)
      从上面的定义代换可以得到,这里简单说一说为什么(k\%2=0)时奇偶位上的数字都相同才是Good String,对于一个Good String(xyxycdots xy)来说,左旋转之后得到的是(yxycdots xyx),有旋转之后得到是(yxyxycdots x)旋转实际上是把原来奇偶位上的数字进行了一个简单的变换,原来奇数位的数字变成偶数位的,偶数位的变成奇数位的.如果不满足(k%2=0)的话,(xyxycdots xyx),左旋转之后是(yxycdots xyxx),二右旋转则是(xxyxycdots xy),这样的两个字符串就不相等了.

    所以可以先从(a_1a_2cdots 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计算从字符串可以提取出(xxxcdots x)这种Good string的长度,然后取其中长度的最大值;通过count_two计算出从字符串中提取出(xyxycdots 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的长度.用字符串总长度减去这个长度得到的就是要删减的字符的数量.

    其它

  • 相关阅读:
    socket入门教程
    线程间操作无效: 从不是创建控件“xxxxxxxx”的线程访问它。
    Socket教程
    Windows 2008 R2防火墙,允许被ping
    Miller_rabin算法+Pollard_rho算法 POJ 1811 Prime Test
    Pollard rho算法+Miller Rabin算法 BZOJ 3668 Rabin-Miller算法
    Miller-Rabin算法 codevs 1702 素数判定 2
    快速幂 cojs 1130. 取余运算
    中国剩余定理 hdu 3579
    中国剩余定理 hdu 1573 X问题
  • 原文地址:https://www.cnblogs.com/2018slgys/p/13405065.html
Copyright © 2011-2022 走看看