[Explanations] A Horrible Poem

Subject to the effect

        A string S is given by the lower case letters, and then given a query q, the shortest cycle required to answer a substring of S section.

        If the B string is the string loop section A, then A may be repeated several times to obtain a B.

 

Input Format

        The first line of a positive integer n, the length S.

        The second line n lowercase letters, a string representing the S.

        The third row a positive integer q, represents the number of interrogation.

        The following two lines each line q positive integers a, b, represents the query string S [a..b] Section shortest cycle length.

 

Output Format

        Q rows are sequentially output a positive integer, a positive integer corresponding to the i-th row of the i-th answer inquiries.

 

SAMPLE INPUT

8

aaabcabc

3

1 3

3 8

4 8

 

Sample Output

1

3

5

 

data range

        1≤a≤b≤n≤5×10^5​​ , q≤2×10^5。

 

answer

        Easy to think, for each sub-string, we want to enumerate its circulation section, and the length of the loop section must be the length of the substring factor. So the key is to enumerate all the factors for each number.

        For each sub-string, with $ O (\ sqrt {n}) $ obviously the simple enumeration TLE. So we want to change an enumeration method.

        We first determined the Euler mesh 1 ... $ n $ primes all, according to the Euler enumeration order screen, the way we can obtain any number $ I $ minimum quality factor $ mp [i] $.

        This enumerate what use is it? In fact, we can find any length $ len $ of all prime factors based on this.

        We $ t [i] $ denotes $ len $ of $ I $ a prime factors, we continue to record $ mp [len] $, then let $ len = \ frac {len} {mp [len]} $, until $ len = 1 $ so far. At this time, we can get the $ $ $ len th prime factors CNT $ $ t [1 ... cnt] $, and there is $ t [i] \ leqslant t [i + 1] $.

        We set the minimum length of loop section $ len $. Initially we then $ len $ equal to the length of the substring.

        We then the $ t [1] $ begins the enumeration $ t [i] $, we let $ len = \ frac {len} {t [i]} $, and then determines whether this case $ $ len circulating section length, if not, let $ $ len back by $ t [i] $. Analyzing continued after enumeration $ t [i] $ to. So that we can continue to get smaller and smaller sections of cycle length, until the answer.

#include <iostream>
#include <cstdio>
#include <cctype>

#define MAX_N (500000 + 5)

#define SIZE (1 << 21) 

#define Getchar() (pr1 == pr2 && (pr2 = (pr1 = fr) + fread(fr, 1, SIZE, stdin), pr1 == pr2) ? EOF : *pr1++) 
#define Putchar(ch) (pw < SIZE ? fw[pw++] = (ch) : (fwrite(fw, 1, SIZE, stdout), fw[(pw = 0)++] = (ch))) 

using namespace std;

char fr[SIZE], * pr1 = fr, * pr2 = fr;
char fw[SIZE];
int pw;

int Read() 
{
    int res = 0, sign = 1;
    char ch = Getchar();
    while(!isdigit(ch)) 
    {
        if(ch == '-') sign = -1;
        ch = Getchar();
    }
    while(isdigit(ch)) 
    {
        res = res * 10 + ch - '0';
        ch = Getchar();
    }
    return res * sign;
}

void Write(int val) 
{
    char a[15];
    int len = 0;
    if(val < 0) 
    {
        val = -val;
        Putchar('-');
    }
    do 
    {
        a[++len] = val % 10 + '0';
        val /= 10;
    }
    while(val);
    while(len) 
    {
        Putchar(a[len--]);
    }
    return;
}

typedef unsigned long long ull;
typedef const unsigned long long cull;
int n;
char s[MAX_N];
cull b = 29;
ull h[MAX_N], pb[MAX_N];
int p[MAX_N], mp[MAX_N], tot;

void Euler() 
{
    for(register int i = 2; i <= n; ++i) 
    {
        if(!mp[i]) p[++tot] = mp[i] = i;
        for(register int j = 1; i * p[j] <= n; ++j) 
        {
            mp[i * p[j]] = p[j];
            if(!(i % p[j])) break;
        }
    }
    return; 
}

void Hash()
{
    pb[0] = 1;
    for(register int i = 1; i <= n; ++i) 
    {
        h[i] = h[i - 1] * b + s[i] - 'a' + 1;
        pb[i] = pb[i - 1] * b;
    } 
    return;
}

ull Value(int lt, int rt) 
{
    return h[rt] - h[lt - 1] * pb[rt - lt + 1];
}

int main() 
{
    n = Read();
    for(register int i = 1; i <= n; ++i) 
    {
        s[i] = Getchar();
    }
    Euler();
    Hash();
    int q, lt, rt;
    q = Read();
    int t[MAX_N], cnt, len;
    while(q--) 
    {
        lt = Read();
        rt = Read();
        len = rt - lt + 1;
        cnt = 0;
        while(len > 1) 
        {
            t[++cnt] = mp[len];
            len /= mp[len];
        }
        len = rt - lt + 1;
        for(register int i = 1; i <= cnt; ++i)
        {
            len /= t[i];
            if(Value(lt, rt - len) != Value(lt + len, rt)) len *= t[i];
        }
        Write(len);
        Putchar('\n');
    }
    fwrite(fw, 1, pw, stdout);
    return 0;
}
Reference program

 

Guess you like

Origin www.cnblogs.com/kcn999/p/11227819.html