CF1109B
我们对数据进行观察/分析归纳,易得出要么 $k\leq 2$,要么无解。
采用构造法证明:
先排除无解的情况:若 $s$ 为偶回文,那么所有字符相等必定无解;若为奇回文,则除去中心字符以外的所有字符相等时无解。
对于剩下的情况,从前往后找到第一个与 $s_1$ 不同的字符(下标从 $1$ 开始),设它处于位置 $i$。接下来考虑把花两次把字符串分成 $3$ 个部分:$[1,i],[i+1,n-i],[n-i+1,n]$。交换第一个和第三个部分,便是一种合法的方案。这种方案 $k=2$。
但在有些情况下答案是否可能为 $1$?答案是肯定的。当 $k=1$ 时我们不妨枚举唯一的一刀切在哪里,然后判断是否为回文以及和原串是否相等即可。
判断是否相等可以使用字符串哈希。
时间复杂度线性。
#include <bits/stdc++.h>
#define FL(i, a, b) for(int i = (a); i <= (b); i++)
#define FR(i, a, b) for(int i = (a); i >= (b); i--)
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const ll base = 27, p = 2654404609;
int n; ll s[2][N], pw[N];
char str[N];
ll ch(int l, int r, int t){
if(!t) return (s[0][r] - s[0][l - 1] * pw[r - l + 1] % p + p) % p;
return (s[1][l] - s[1][r + 1] * pw[r - l + 1] % p + p) % p;
}
int main(){
scanf("%s", str + 1), n = strlen(str + 1), pw[0] = 1;
FL(i, 1, n) pw[i] = pw[i - 1] * base % p;
FL(i, 1, n) s[0][i] = s[0][i - 1] * base % p + (str[i] - 'a');
FR(i, n, 1) s[1][i] = s[1][i + 1] * base % p + (str[i] - 'a');
FL(i, 2, n){
ll z = (ch(i, n, 0) * pw[i - 1] + ch(1, i - 1, 0)) % p;
ll f = (ch(1, i - 1, 1) * pw[n - i + 1] + ch(i, n, 1)) % p;
if(z == ch(1, n, 0) || z != f) continue;
printf("1\n"); return 0;
}
FL(i, 2, n / 2) if(str[i] != str[1]){
printf("2\n"); return 0;
}
printf("Impossible\n");
return 0;
}

浙公网安备 33010602011771号