Luogu P11190:给定一个长度为
$2|n$ ,且$s$ 中每个字符的出现次数都不超过$\frac n2$ 。
尝试两两配对,维护两个数组
注意 beg
表示将要拆哪一对。
如果
$s$ 中仅有a
和b
。
记出现次数多的为 m
,另外一种字符叫 l
。也是两两配对,一个 m
对一个 l
,设匹配了 m
。把剩下的分成两部分:
- A 是第一个
l
左边的m
,设有$a$ 个。 - B 是第一个
l
右边的m
,设有$b$ 个。
A 和 B 都可能是空串。下面每个分类讨论都在否定它上面假设的前提下进行,不能交换顺序。
-
$t=0$ :无解 -
lm
:lmB
-
ml
且$a+1\ne b$ :mAlB
-
ml
且$a+1=b$ 且$t=1$ :无解 -
ml ml
且$a+1=b$ :AlB mml
-
ml lm
且$a+1=b$ :mAl lmB
如果不满足特殊性质 I,那么存在唯一的出现最多的字符
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
const int N = 1e5+5;
int t, n, cnt[26], f[N], g[N];
char m;
std::vector<int> a, b;
std::string st;
std::ostringstream sout;
void woa() {
int ft = 0, tl = 0;
for (int i = 1; i <= n; i++)
if (ft == tl || st[f[tl]] == st[i]) f[ft++] = i;
else g[tl++] = i;
int beg = 0;
while (ft - tl >= 2) {
while (st[f[beg]] == st[f[ft-1]] ||
st[g[beg]] == st[f[ft-1]]) beg++;
g[tl] = f[tl];
f[tl++] = g[beg];
g[beg++] = f[--ft];
} // ababcccc
int tag = -1;
if (ft > tl) do tag++;
while (st[f[tag]] == st[f[ft-1]]);
std::cout << "Huoyu\n" << tl << '\n';
for (int i=0; i<tl; i++) {
if (i == tag && g[i] > f[ft-1])
std::swap(g[i], f[ft-1]);
std::cout << "23"[i==tag] << ' ' << f[i] << ' ' << g[i];
if (i == tag) std::cout << ' ' << f[ft-1];
std::cout << '\n';
}
}
void wob() {
int i=0, j=0, top=0;
while (true) {
do j++; while (j <= n && st[j] == m);
if (j > n) break;
do i++; while (st[i] != m);
if (i < j) f[top] = i, g[top] = j;
else f[top] = j, g[top] = i;
top++;
}
if (!top) {
std::cout << "Shuiniao\n";
return;
}
int pos = (st[f[0]] == m ? g[0] : f[0]);
a.clear(), b.clear();
while (true) {
do i++; while (i <= n && st[i] != m);
if (i > n) break;
if (i < pos) a.emplace_back(i);
else b.emplace_back(i);
}
int va = a.size(), vb = b.size();
sout.str(""), pos = 0;
sout << "Huoyu\n" << top << '\n';
if (st[f[0]] != m) {
sout << vb + 2 // lmB
<< ' ' << f[0] << ' ' << g[0];
for (int x : b) sout << ' ' << x;
pos = 1, sout << '\n';
} else if (va + 1 != vb) {
sout << va + vb + 2 << ' ' << f[0]; // mAlB
for (int x : a) sout << ' ' << x;
sout << ' ' << g[0];
for (int x : b) sout << ' ' << x;
pos = 1, sout << '\n';
} else if (top == 1) {
std::cout << "Shuiniao\n";
return;
} else if (st[f[1]] == m) {
sout << va + vb + 1; // AlB
for (int x : a) sout << ' ' << x;
sout << ' ' << g[0];
for (int x : b) sout << ' ' << x;
sout << "\n3 " << f[0] << ' ' << f[1] // mml
<< ' ' << g[1] << '\n', pos = 2;
} else {
sout << va + 2 << ' ' << f[0]; // mAl
for (int x : a) sout << ' ' << x;
sout << ' ' << g[0] << '\n' // lmB
<< vb + 2 << ' ' << f[1] << ' ' << g[1];
for (int x : b) sout << ' ' << x;
sout << '\n', pos = 2;
}
for (std::cout << sout.str(); pos < top; pos++)
std::cout << "2 " << f[pos] << ' ' << g[pos] << '\n';
}
int main() {
std::cin >> t >> t;
while (t--) {
std::cin >> n >> st, st = ' ' + st;
for (int i=0; i<26; i++) cnt[i] = 0;
for (int i=1; i<=n; i++) cnt[st[i] - 'a']++;
m = 0;
for (int i=1; i<26; i++)
if (cnt[i] > cnt[m]) m = i;
m += 'a';
if (cnt[m-'a'] * 2 <= n) woa(); else wob();
}
}