列表

详情


NC50316. A Horrible Poem

描述

给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节。
如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到。

输入描述

第一行一个正整数n,表示S的长度。
第二行n个小写英文字母,表示字符串S。
第三行一个正整数q,表示询问个数。
下面q行每行两个正整数a,b,表示询问字符串S[a..b]的最短循环节长度。

输出描述

依次输出q行正整数,第i行的正整数对应第i个询问的答案。

示例1

输入:

8
aaabcabc
3
1 3
3 8
4 8

输出:

1
3
5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 1161ms, 内存消耗: 20452K, 提交时间: 2019-12-08 16:07:00

#include<bits/stdc++.h>
using namespace std;
const unsigned P = 1e9+7;
const int MAXN = 5e5+7;
unsigned H[MAXN];
unsigned B[MAXN];
char s[MAXN];
int primes[MAXN];
int p_sz;
int factor[MAXN];
int readInt() {
  int a = 0;
  char c;
  while (isdigit(c = getchar()))  {
    a = a * 10 + c - '0';
  }
  return a;
}
int main() {
  int n; scanf("%d", &n);
  scanf("%s", s);
  for (int i = 2; i <= n; i++) {
    if (!factor[i]) primes[p_sz++] = i, factor[i] = i;
    for (int j = 0; j < p_sz; j++) {
      int p = primes[j];
      long long s = (long long) p * i;
      if (s > n) break;
      factor[s] = p;
      if (i % p == 0) break;
    }
  }

  for (int i = 0; i < n; i++) H[i+1] = H[i] * P + s[i];
  for (int i = 0; i <= n; i++) B[i] = i?B[i-1]*P:1;
  int q; scanf("%d", &q);
  while (q--) {
    int a, b; scanf("%d %d", &a, &b);
    int L = b - a + 1;
    int ans = L;
    while (L != 1) {
      int p = factor[L];
      while (L % p == 0) {
        int i = ans / p;
        if (H[a+ans-1] - H[a+i-1]*B[ans-i] == H[a+ans-i-1] - H[a-1]*B[ans-i])  {
          ans /= p, L /= p;
        } else break;
      }
      while (L%p== 0) L /= p;
    }
    printf("%d\n", ans);
  }
}

C++ 解法, 执行用时: 878ms, 内存消耗: 26232K, 提交时间: 2021-08-19 20:25:49

#include<bits/stdc++.h>
using namespace std;
const int MAXN=500011;
long long e[MAXN]={1},h[MAXN];
long long Hash(int l,int r){l--;return h[r]-h[l]*e[r-l];}
int n,q,p[MAXN],f[MAXN];
char s[MAXN];
int main()
{
	scanf("%d%s%d",&n,s+1,&q);
	for(int i=1;i<=n;i++)e[i]=e[i-1]*31,h[i]=h[i-1]*31+(s[i]-'a'+1);
	for(int i=2;i<=n;i++)
		if(!f[i])
			for(int j=i;j<=n;j+=i)f[j]=1,p[j]=i;
	while(q--)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		int len=b-a+1;
		for(int i=len;i>1;i/=p[i])
			if(Hash(a,b-len/p[i])==Hash(a+len/p[i],b))len/=p[i];
		printf("%d\n",len);
	}
}

上一题