杭电多校第八场 Isomorphic Strings(最小表示法,循环同构)

本文主要是介绍杭电多校第八场 Isomorphic Strings(最小表示法,循环同构),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Problem Description
It is preferrable to read the pdf statment.

Two strings are called cyclical isomorphic if one can rotate one string to get another one. ‘Rotate’ here means ‘‘to take some consecutive chars (maybe none) from the beginning of a string and put them back at the end of the string in the same order’’. For example, string ‘‘abcde’’ can be rotated to string ‘‘deabc’’.

Now that you know what cyclical isomorphic is, Cuber QQ wants to give you a little test.

Here is a string s of length n. Please check if s is a concatenation of k strings, s1,s2,⋯,sk (k>1), where,

k is a divisor of n;

s1,s2,…,sk are of equal length: nk;

There exists a string t, which is cyclical isomorphic with si for all 1≤i≤k.

Print ‘‘Yes’’ if the check is positive, or ‘‘No’’ otherwise.

Input
The first line contains an integer T (1≤T≤1000), denoting the number of test cases. T cases follow.

The first line of each test case contains an integer n (1≤n≤5⋅106).

The second line contains a string s of length n consists of lowercase letters only.

It is guaranteed that the sum of n does not exceed 2⋅107.

Output
For each test case, output one line containing ‘‘Yes’’ or ‘‘No’’ (without quotes).

Sample Input
6
1
a
2
aa
3
aab
4
abba
6
abcbcc
8
aaaaaaaa

Sample Output
No
Yes
No
Yes
No
Yes

Source
2020 Multi-University Training Contest 8

题意:
将一个字符串分成k组,要求每一组都是循环同构。问是否存在这样的分法(k≥2)

思路:
k为所有字母出现次数的gcd的因数。
然后k肯定只有几百,每次再剪枝判断一下每一组的个数是否符合要求就够了。
每一组判断是否循环同构可以用最小表示法。
理论复杂度至少有4e9吧,但是因为很容易就break掉所以复杂度不会那么多,所以水过了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <iostream>
#include <map>
#include <string>
#include <set>typedef long long ll;
using namespace std;const int maxn = 5e6 + 7;int sum[maxn][30];
char s[maxn];
char sta[maxn],ed[maxn];
int b[maxn]; //每个的最小表示int mini(int n,char *tmp) {// 最小表示法int ans = 1;for (int i = 1; i <= n; i++) tmp[n+i] = tmp[i];int i = 1, j = 2, k;while (i <= n && j <= n) {for (k = 0; k < n && tmp[i+k] == tmp[j+k]; k++);if (k == n) break; // s likes "aaaaa"if (tmp[i+k] > tmp[j+k]) {i = i + k + 1;if (i == j) i++;} else {j = j + k + 1;if (i == j) j++;}}ans = min(i, j); //tmp[ans]是最小表示return ans;
}bool equal(int p1,int p2,int len) {for(int i = 1;i <= len;i++) {int x = (i + p1 - 2) % len + 1;int y = (i + p2 - 2) % len + 1;if(sta[x] != ed[y]) return false;}return true;
}bool check(int n,int k) { //分了k组if(k == 1) return false;int len = n / k;for(int i = 0;i < 26;i++) {if(sum[n][i] == 0) continue;int dat = sum[n][i] / k;for(int j = 1;j <= k;j++) {int l = (j - 1) * len + 1;int r = j * len;int num = sum[r][i] - sum[l - 1][i];if(num != dat) return false;}}for(int i = 1;i <= len;i++) {sta[i] = s[i];}b[1] = mini(len,sta);for(int i = 2;i <= k;i++) {int l = (i - 1) * len + 1;int r = i * len;for(int j = l;j <= r;j++) {ed[j - l + 1] = s[j];}b[i] = mini(len,ed);if(!equal(b[1],b[i],len)) {return false;}}return true;
}int gcd(int x,int y) {return y == 0 ? x : gcd(y,x % y);
}vector<int>DIV(int x) { //质因数分解int t = sqrt(x) + 1;vector<int>ans;for(int i = 2;i <= t;i++) {if(x % i == 0) {ans.push_back(i);if(x / i != i) {ans.push_back(x / i);}}}return ans;
}int main() {int T;scanf("%d",&T);while(T--) {int n;scanf("%d",&n);scanf("%s",s + 1);for(int i = 1;i <= n;i++) {int ch = s[i] - 'a';for(int j = 0;j < 26;j++) sum[i][j] = sum[i - 1][j];sum[i][ch]++;}int now = 0;for(int i = 0;i < 26;i++) {if(sum[n][i]) {if(!now) now = sum[n][i];else now = gcd(now,sum[n][i]);}}vector<int>div = DIV(now);div.push_back(now);int flag = 0;for(int i = 0;i < div.size();i++) {int v = div[i];if(check(n,v)) {printf("Yes\n");flag = 1;break;}}if(!flag) {printf("No\n");}}return 0;
}

这篇关于杭电多校第八场 Isomorphic Strings(最小表示法,循环同构)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/907319

相关文章

Java中的for循环高级用法

《Java中的for循环高级用法》本文系统解析Java中传统、增强型for循环、StreamAPI及并行流的实现原理与性能差异,并通过大量代码示例展示实际开发中的最佳实践,感兴趣的朋友一起看看吧... 目录前言一、基础篇:传统for循环1.1 标准语法结构1.2 典型应用场景二、进阶篇:增强型for循环2.

Python循环结构全面解析

《Python循环结构全面解析》循环中的代码会执行特定的次数,或者是执行到特定条件成立时结束循环,或者是针对某一集合中的所有项目都执行一次,这篇文章给大家介绍Python循环结构解析,感兴趣的朋友跟随... 目录for-in循环while循环循环控制语句break语句continue语句else子句嵌套的循

MySQL存储过程之循环遍历查询的结果集详解

《MySQL存储过程之循环遍历查询的结果集详解》:本文主要介绍MySQL存储过程之循环遍历查询的结果集,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言1. 表结构2. 存储过程3. 关于存储过程的SQL补充总结前言近来碰到这样一个问题:在生产上导入的数据发现

Nginx部署React项目时重定向循环问题的解决方案

《Nginx部署React项目时重定向循环问题的解决方案》Nginx在处理React项目请求时出现重定向循环,通常是由于`try_files`配置错误或`root`路径配置不当导致的,本文给大家详细介... 目录问题原因1. try_files 配置错误2. root 路径错误解决方法1. 检查 try_f

Spring三级缓存解决循环依赖的解析过程

《Spring三级缓存解决循环依赖的解析过程》:本文主要介绍Spring三级缓存解决循环依赖的解析过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、循环依赖场景二、三级缓存定义三、解决流程(以ServiceA和ServiceB为例)四、关键机制详解五、设计约

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

C# foreach 循环中获取索引的实现方式

《C#foreach循环中获取索引的实现方式》:本文主要介绍C#foreach循环中获取索引的实现方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、手动维护索引变量二、LINQ Select + 元组解构三、扩展方法封装索引四、使用 for 循环替代

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Python循环缓冲区的应用详解

《Python循环缓冲区的应用详解》循环缓冲区是一个线性缓冲区,逻辑上被视为一个循环的结构,本文主要为大家介绍了Python中循环缓冲区的相关应用,有兴趣的小伙伴可以了解一下... 目录什么是循环缓冲区循环缓冲区的结构python中的循环缓冲区实现运行循环缓冲区循环缓冲区的优势应用案例Python中的实现库