[Daimayuan]循环子串(C++,字符串)

题目描述

一个字符串 S S S是另一字符串 T T T的循环子串当且仅当存在 k k k, T T T所有字符循环右移 k k k位后得到的新串 T ′ T′ T,满足 S S S T ′ T′ T的子串。

例如: abccefab的循环子串。 (cefab循环右移 2 2 2位得到abcef, abcabcef的子串)

一个串 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 1t100, 1 ≤ n ≤ 1 0 3 1≤n≤10^3 1n103, ∑ n ≤ 1 0 3 \sum n≤10^3 n103

样例输入
2
4
ccca
11
eeaafbddfaa
样例输出
YES
NO
提示
  1. 本道题目只需要语法知识就可以解决。

  2. 任意子串是什么意思呢?

  3. 如果一个子串包含另一个子串,那么我们是不是只需要求出大子串的合法情况,就可以推出小子串的合法情况。

  4. 从大的子串向小的子串考虑 最大的子串是什么呢?

解题思路

假设abc是循环子串,那么cba也应该是循环子串,则有***abc***cba***

*注:这里将abccba调换也可以,*的数量可以是任意的

进一步假设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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WitheredSakura_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值