杭电多校第八场 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

相关文章

Python循环缓冲区的应用详解

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

Java嵌套for循环优化方案分享

《Java嵌套for循环优化方案分享》介绍了Java中嵌套for循环的优化方法,包括减少循环次数、合并循环、使用更高效的数据结构、并行处理、预处理和缓存、算法优化、尽量减少对象创建以及本地变量优化,通... 目录Java 嵌套 for 循环优化方案1. 减少循环次数2. 合并循环3. 使用更高效的数据结构4

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

Python判断for循环最后一次的6种方法

《Python判断for循环最后一次的6种方法》在Python中,通常我们不会直接判断for循环是否正在执行最后一次迭代,因为Python的for循环是基于可迭代对象的,它不知道也不关心迭代的内部状态... 目录1.使用enuhttp://www.chinasem.cnmerate()和len()来判断for

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在

JAVA中while循环的使用与注意事项

《JAVA中while循环的使用与注意事项》:本文主要介绍while循环在编程中的应用,包括其基本结构、语句示例、适用场景以及注意事项,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录while循环1. 什么是while循环2. while循环的语句3.while循环的适用场景以及优势4. 注意

Python中的异步:async 和 await以及操作中的事件循环、回调和异常

《Python中的异步:async和await以及操作中的事件循环、回调和异常》在现代编程中,异步操作在处理I/O密集型任务时,可以显著提高程序的性能和响应速度,Python提供了asyn... 目录引言什么是异步操作?python 中的异步编程基础async 和 await 关键字asyncio 模块理论

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

poj 1287 Networking(prim or kruscal最小生成树)

题意给你点与点间距离,求最小生成树。 注意点是,两点之间可能有不同的路,输入的时候选择最小的,和之前有道最短路WA的题目类似。 prim代码: #include<stdio.h>const int MaxN = 51;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int P;int prim(){bool vis[MaxN];