个人思路:先求两边再求中间,二分 + hash
#include <bits/stdc++.h>
#define F first
#define S second
#define mp make_pair
#define int long long
#define VI vector<int>
#define PII pair<int, int>
#define ms(a, b) memset(a, b, sizeof(a))
#define _for(i, a, b) for (int i = (int)(a); i <= (int)(b); i ++ )
#define _all(i, a, b) for (int i = (int)(a); i >= (int)(b); i -- )
using namespace std;
const int N = 1e5 + 5, P = 1e9 + 7;
int n, p[N], h[N][2]; // 0正向Hash, 1反向Hash
PII res;
char s[N];
inline int Hash0(int l, int r) { return ((h[r][0] - h[l - 1][0] * p[r - l + 1]) % P + P) % P; }
inline int Hash1(int l, int r) { return ((h[l][1] - h[r + 1][1] * p[r - l + 1]) % P + P) % P; }
inline VI Manacher(char * s, int len) {
VI res(len + 5);
int l = 1, r = - 1, k;
_for (i, 1, len) {
k = (i > r ? 1 : min(res[l + r - i], r - i + 1));
while (1 <= i - k && i + k <= len && s[i - k] == s[i + k]) k ++ ;
res[i] = k -- ;
if (i + k > r) l = i - k, r = i + k;
}
return res;
}
inline int check(int x) {
_for (i, 1, n) if (i + x - 1 < n - x + 1 && Hash0(i, i + x - 1) == Hash1(n - x + 1, n)) return i;
return 0;
}
inline void binary_search() {
int l = 1, r = n / 2;
while (l <= r) {
int mid = (l + r) >> 1, cur = check(mid);
if (cur) res = mp(mid, cur), l = mid + 1;
else r = mid - 1;
}
}
inline bool is_palin(char * s, int len) {
_for (i, 1, (len >> 1)) if (s[i] != s[len - i + 1]) return 0;
return 1;
}
signed main() {
scanf("%s", s + 1), n = strlen(s + 1);
VI v = Manacher(s, n);
_for (i, 1, n) if ((v[i] << 1) - 1 == n) { printf("1\n1 %lld\n", n); return 0; }
if (is_palin(s, n)) { printf("1\n1 %lld\n", ((n & 1) ? n : n - 1)); return 0; }
p[0] = 1;
_for (i, 1, n) p[i] = p[i - 1] * 27 % P, h[i][0] = (h[i - 1][0] * 27 + (s[i] - 'a' + 1)) % P;
_all (i, n, 1) h[i][1] = (h[i + 1][1] * 27 + (s[i] - 'a' + 1)) % P;
binary_search();
if (! res.F) {
int ans1 = 0;
_for (i, 1, n) if (v[ans1] < v[i]) ans1 = i;
printf("1\n%lld %lld\n", ans1 - v[ans1] + 1, (v[ans1] << 1) - 1);
return 0;
}
int L = res.S + res.F, R = n - res.F, radius, ans_r = 0, mid = 0;
_for (i, L, R) {
if (L <= i - v[i] + 1 && i + v[i] - 1 <= R) { if (v[i] > ans_r) mid = i, ans_r = v[i]; }
else {
radius = min(v[i], min(i - L + 1, R - i + 1));
if (radius > ans_r) mid = i, ans_r = radius;
}
}
printf("3\n%lld %lld\n%lld %lld\n%lld %lld\n", res.S, res.F, mid - ans_r + 1, (ans_r << 1) - 1, n - res.F + 1, res.F);
return 0;
}