题目大意
给出 n n n个字符,节点编号为 [ 0 , n ] [0,n] [0,n],第 i i i个字符若为 L L L代表节点 i i i到节点 i − 1 i-1 i−1有一条有向边,否则代表节点 i − 1 → i i-1 \rightarrow i i−1→i有一条有向边。如果从一个点走到另外一个点,那么所有边的方向会立刻反向。分别输出从每个节点出发能经历的所有节点个数。
解题思路
首先手玩一下样例,不难发现如果一个点可以向某个方向不断走,那么那个方向的 L R LR LR一定是交替出现的!而且走到终点一定可以原路返回,这启发我们,只要能预处理出每个节点向左和向右能走的最大距离,只需要顺序枚举相邻两字符是否相等然后同理逆序枚举。
但是本题容易把人搞晕,就是不能把每个点本身算进去,因为 L , R L,R L,R这些标记是在相邻两点的边上的。还有就是注意首尾节点特殊处理一下。
//
// Created by Happig on 2021/1/30.
//
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define ENDL "\n"
#define lowbit(x) (x & (-x))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double dinf = 1e300;
const ll INF = 1e18;
const int Mod = 998244353;
const int maxn = 3e5 + 10;
int L[maxn], R[maxn];
int main() {
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t, n;
string s;
cin >> t;
while (t--) {
cin >> n;
cin >> s;
string res = "";
res += s[0], res += s, res += s[n - 1];
s = res;
for (int i = 1; i <= n; i++) {
if (s[i] != s[i - 1]) L[i] = L[i - 1] + 1;
else L[i] = 1;
}
for (int i = n; i >= 1; i--) {
if (s[i] != s[i + 1]) R[i] = R[i + 1] + 1;
else R[i] = 1;
}
// for (int i = 1; i <= n; i++) cout << L[i] << " ";
// cout << ENDL;
// for (int i = 1; i <= n; i++) cout << R[i] << " ";
// cout << ENDL;
cout << (s[0] == 'L' ? 1 : R[1] + 1) << " ";
for (int i = 1; i < n; i++) {
int ans = 1;
if (s[i] == 'L') ans += L[i];
if (s[i + 1] == 'R') ans += R[i + 1];
cout << ans << " ";
}
cout << (s[n] == 'R' ? 1 : L[n] + 1) << ENDL;
}
return 0;
}