题目描述
一个字符串 S S S是另一字符串 T T T的循环子串当且仅当存在 k k k, T T T所有字符循环右移 k k k位后得到的新串 T ′ T′ T′,满足 S S S是 T ′ T′ T′的子串。
例如: abc
是 cefab
的循环子串。 (cefab
循环右移
2
2
2位得到abcef
, abc
是abcef
的子串)
一个串
P
P
P是完全循环串当且仅当对于它的任一子串
H
H
H, 都有
H
r
e
v
e
r
s
e
Hreverse
Hreverse是
P
P
P的循环子串 (
H
r
e
v
e
r
s
e
Hreverse
Hreverse 为
H
H
H的倒转, 如abc
r
e
v
e
r
s
e
reverse
reverse后 为cba
)。
给一个长度为 n n n的字符串, 判断它是不是完全循环串。
输入格式
第一行一个正整数 t t t, 表示测试数据组数。
对于每一组数据,第一行一个正整数 n n n, 表示字符串的长度。接下来一行一个长度为 n n n的字符串. 仅包含小写字母。
输出格式
对于每组测试数据,如果这个串是完全循环串, 输出YES
,否则输出NO
。每组测试数据之间输出换行。
数据范围
对于所有数据 有 1 ≤ t ≤ 100 1≤t≤100 1≤t≤100, 1 ≤ n ≤ 1 0 3 1≤n≤10^3 1≤n≤103, ∑ n ≤ 1 0 3 \sum n≤10^3 ∑n≤103。
样例输入
2
4
ccca
11
eeaafbddfaa
样例输出
YES
NO
提示
-
本道题目只需要语法知识就可以解决。
-
任意子串是什么意思呢?
-
如果一个子串包含另一个子串,那么我们是不是只需要求出大子串的合法情况,就可以推出小子串的合法情况。
-
从大的子串向小的子串考虑 最大的子串是什么呢?
解题思路
假设abc
是循环子串,那么cba
也应该是循环子串,则有***abc***cba***
*注:这里将abc
与cba
调换也可以,*
的数量可以是任意的
进一步假设abcd
是循环子串,则有***abcd*dcba***
不难发现,如果abcd
是循环子串,则abc
自然也是循环子串
所以我们只需要证明最大的循环子串符合条件即可
也就是将给定字符串反转,然后寻找其是否存在
而对于可以循环右移的字符串,我们只需要将其复制然后拼接,在处理之后的字符串中寻找即可
AC代码如下
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int max_t = 100;
const int max_n = 1e3;
string str;
int t, len;
int main() {
cin >> t;
for (int i = 0; i < t; i++) {
cin >> len >> str;
string rev = str;
reverse(rev.begin(), rev.end());
str = str + str;
if (str.find(rev) != -1)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}