题目
思路
贪心
+
+
+ 暴力枚举。
这题要求截取最少数量的字符串,使得每个字符串在所有各自的循环字符串中字典序最小。
首先,枚举截取字符串的开始位置。
然后,枚举截取的长度(从长到短,贪心)。
接着,截字符串。
最后判断当前字符串是否为字典序最小的字符串。
那么,判断的时候如何截取循环字符串呢?
① 先从当前位置截取到最后,再从开始截取到当前位置,将这两段结合在一起。
结合的操作string就很好实现了。直接
+
+
+ 即可。
实现方法:
bool judge(string s) {
string x;
int n = s.size();
for (int i = 1; i < n; i++) {
x = s.substr(i, n-i) + s.substr(0, i);
if (x < s) return false;
}
return true;
}
② 开两倍的字符串。
比如
a
b
c
d
⇒
a
b
c
d
a
b
c
d
abcd \Rightarrow abcdabcd
abcd⇒abcdabcd
这里同样用string很好实现。
这样就可以直接截取了。
实现方法:
bool judge(string s) {
string x;
int n = s.size();
string ss = s+s;
for (int i = 0; i < n; i++) {
x = ss.substr(i, n);
if (x < s) return false;
}
return true;
}
代码
1:
//1
#include <bits/stdc++.h>
using namespace std;
bool judge(string s) {
string x;
int n = s.size();
for (int i = 1; i < n; i++) {
x = s.substr(i, n-i) + s.substr(0, i);
if (x < s) return false;
}
return true;
}
int main() {
int T; scanf("%d", &T);
string s, x;
while (T--) {
cin >> s;
int n = s.size();
for (int j = 0; j < n; ) {
for (int k = n - j; k >= 0; k--) {
x = s.substr(j, k);
if(judge(x)) {
cout << x << " ";
j = j + k;
break;
}
}
}
puts("");
}
return 0;
}
2:
//2
#include <bits/stdc++.h>
using namespace std;
bool judge(string s) {
string x;
int n = s.size();
string ss = s+s;
for (int i = 0; i < n; i++) {
x = ss.substr(i, n);
if (x < s) return false;
}
return true;
}
int main() {
int T; scanf("%d", &T);
string s, x;
while (T--) {
cin >> s;
int n = s.size();
for (int i = 0; i < n; )
for (int j = n - i; j >= 0; j--) {
x = s.substr(i, j);
if(judge(x)) {
cout << x << " ";
i = i + j;
break;
}
}
puts("");
}
return 0;
}