2019牛客暑期多校训练营(第七场)A : String
链接:https://ac.nowcoder.com/acm/contest/887/A来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
A string is perfect if it has the smallest lexicographical ordering among its cyclic rotations.
For example: "0101" is perfect as it is the smallest string among ("0101", "1010", "0101", "1010").
Given a 01 string, you need to split it into the least parts and all parts are perfect.
输入描述:
The first line of the input gives the number of test cases, T (T≤300)T\ (T \leq 300)T (T≤300). test cases follow.
For each test case, the only line contains one non-empty 01 string. The length of string is not exceed 200.
输出描述:
For each test case, output one string separated by a space.
示例1
输入
复制
4
0
0001
0010
111011110
输出
复制
0
0001
001 0
111 01111 0
题意: 将输入的字符串分最少的次数, 使得每个串都是其循环串中字典序最小的。
思路:可以使用最小表示法, 从后向前, 找到当前字典序最小的循环串位置,注意
找到的串, 仍要继续判断是否为当前最小循环串, 直到满足条件即可以分割。
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 10; string ans[N]; int get_num(string s) // 最小表示法, 返回的为下标 { int k = 0, i = 0, j = 1; int n = s.size(); while (k < n&&i < n&&j < n) { if (s[(i + k) % n] == s[(j + k) % n]) { k++; } else { s[(i + k) % n] > s[(j + k) % n] ? i = i + k + 1 : j = j + k + 1; if (i == j) i++; k = 0; } } i = min(i, j); return i; } int main(){ int t; cin >> t; while (t--) { int cnt = 0; string s; cin >> s; int len = s.size(); int i = len; // 从后往前的位置 for (;;) { if (i <= 0) // 分完了 break; int wz = get_num(s); string now = s.substr(wz); int nwz = 0; while (true) // 直到当前的串最小表示即为0号下标开始 { nwz = get_num(now); // 当前串最小表示的位置 now = now.substr(nwz); if (nwz == 0) // 为当前最小串 break; } ans[++cnt] = now; int len1 = now.size(); i -= len1; s = s.substr(0, i); } for (int i = cnt; i >= 1; i--) if (i != 1) cout << ans[i] << " "; else cout << ans[i] << endl; } return 0; }