zoukankan      html  css  js  c++  java
  • BZOJ2795: [Poi2012]A Horrible Poem

    Description

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

    Input

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

    Output

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

    Sample Input

    8
    aaabcabc
    3
    1 3
    3 8
    4 8

    Sample Output

    1
    3
    5

    Solution

    qsqrt(n)做法的话,可以枚举到sqrt(n),另外一半除出来存到数组里面,如果跑完没找到循环节的话那么最近存进数组里面的就是答案了。但是这样基本要跑满,所以会T,在LOJ能80分。

    nlogn做法的话,可以根据算数基本定理把len分解了,那么对每个质因子,如果len/p是循环节的话,就将len/p,这样子能做到qlogn。

    至于判断是否循环节,如果一个字符串如果有循环节长度为x,则hash(l+x,r)=hash(l,r−x)

    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    
    #define N 2000100
    #define ll unsigned long long
    #define base 233
    
    ll h[N], p[N];
    char s[N];
    int n, f[N], lp[N], pr[N], cnt;
    bool vis[N];
    
    ll get_hash(int l, int r) { return h[r] - h[l - 1] * p[r - l + 1]; }
    
    bool check(int x, int l, int r) {
    	return get_hash(l, r - x) == get_hash(l + x, r);
    }
    
    void pre_test() {
    	p[0] = 1;
    	for(int i = 1; i <= n; ++i) {
    		p[i] = p[i - 1] * base;
    		h[i] = h[i - 1] * base + (ll)s[i];
    	}
    	for(int i = 2; i <= n; ++i) {
    		if(!vis[i]) pr[++cnt] = i, lp[i] = i;
    		for(int j = 1; j <= cnt && i * pr[j] <= n; ++j) {
    			vis[i * pr[j]] = 1;
    			lp[i * pr[j]] = pr[j];
    			if(i % pr[j] == 0) break;
    		}
    	}
    }
    
    int main() {
    	scanf("%d%s", &n, s + 1);
    	pre_test();
    	int m, l, r; scanf("%d", &m);
    	while(m--) {
    		scanf("%d%d", &l, &r);
    		int now = r - l + 1, v = r - l + 1;
    		while(v != 1) {
    			if(check(now / lp[v], l, r)) now /= lp[v];
    			v /= lp[v];
    		}
    		printf("%d
    ", now);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    HDU 4291 A Short problem 第37届ACM/ICPC 成都赛区网络赛1004题 (找规律,取模求循环节)
    POJ 1276 Cash Machine(多重背包)
    HDU 4296 Buildings 第37届ACM/ICPC 成都赛区网络赛1009题 (贪心)
    POJ 2392 Space Elevator (多重背包)
    Mysql配置SSL
    error C2471: cannot update program database vc90.pdb
    Android 总结 转载
    MAX SDK的INode的变换矩阵,以及Object的一些常识
    C++游戏开发需要阅读的书籍
    游戏程序员养成计划
  • 原文地址:https://www.cnblogs.com/henry-1202/p/10317084.html
Copyright © 2011-2022 走看看