[CF] C. Good String - Educational Codeforces Round 92 (Rated for Div. 2)

https://codeforces.com/contest/1389/problem/C

题目大意

给出字符串 $S$ 问最少删掉其中多少个字符,可以使得它向左循环移动一位和向右循环移动一位的串相同。

$2 \le |S| \le 2 \times 10^5$

简要题解

观察:

  1. $2$ 长的串一定行
  2. 同一个字符的串一定行
  3. 两种字符交替的偶数长的串一定行

其实这题样例很强,把所有的情况都覆盖了。

左移一次右移一次相当于右移两次,相当于串有一个 $|S| - 2$ 长的 boarder 和一个 $2$ 长的 $boarder$。因为这两个加起来刚好是 $|S|$ 则其满足弱周期引理的条件,即 $gcd(|S| - 2, 2)$ 也是串的周期,显然如果 $|S|$ 是奇数这个值是 $1$,偶数时是 $2$。也就是说串总有一个不超过 $2$ 的周期,于是我们遍历所有周期的可能即可。

复杂度

$T$:$O(n)$ 有一个 $10 \times 10$ 的大常数。

$S$:$O(n)$

代码实现

#include <bits/stdc++.h>
using namespace std;

int io_=[](){ ios::sync_with_stdio(false); cin.tie(nullptr); return 0; }();

using LL = long long;
using ULL = unsigned long long;
using LD = long double;
using PII = pair<int, int>;
using VI = vector<int>;
using MII = map<int, int>;

template<typename T> void cmin(T &x,const T &y) { if(y<x) x=y; }
template<typename T> void cmax(T &x,const T &y) { if(x<y) x=y; }
template<typename T> bool ckmin(T &x,const T &y) { 
    return y<x ? (x=y, true) : false; }
template<typename T> bool ckmax(T &x,const T &y) { 
    return x<y ? (x=y, true) : false; }
template<typename T> void cmin(T &x,T &y,const T &z) {// x<=y<=z 
    if(z<x) { y=x; x=z; } else if(z<y) y=z; }
template<typename T> void cmax(T &x,T &y,const T &z) {// x>=y>=z
    if(x<z) { y=x; x=z; } else if(y<z) y=z; }

// mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
// mt19937_64 rnd_64(chrono::system_clock::now().time_since_epoch().count());

/*
---------1---------2---------3---------4---------5---------6---------7---------
1234567890123456789012345678901234567890123456789012345678901234567890123456789
*/

void solve() {
  string s; cin >> s;
  int n = s.length();

  int ans = n - 2;
  
  map<char, int> cnt;
  for (char c : s) cnt[c]++;

  for (auto [v, c] : cnt) {
    cmin(ans, n - c);
  }

  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      if (i == j) continue;
      
      int cnt = 0;
      for (int k = 0; k < n; k++) {
        if (cnt & 1) {
          if (s[k] == j + '0') cnt++;
        } else {
          if (s[k] == i + '0') cnt++;
        }
      }

      if (cnt & 1) cnt--;

      cmin(ans, n - cnt);
    }
  }

  cout << ans << '\n';
}

int main() {
  int t = 1; 
  cin >> t;
  while (t--) {
    solve();
  }
  return 0;
}
Prev: [CF] B. Array Walk - Educational Codeforces Round 92 (Rated for Div. 2)
Next: [CF] F. Topforces Strikes Back - Codeforces Round 570 (Div. 3)