• 【hash】A Horrible Poem


    【题目链接】

    # 10038. 「一本通 2.1 练习 4」A Horrible Poem

    【参考博客】

    A Horrible Poem (字符串hash+数论)


    【题目描述】

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

    【算法】-首先对于长度为 lenlen 的子串,循环节长度为 xx 的充要条件:[1lenx][1,len−x]串的哈希值等于 [x+1len][x+1,len] 串的哈希值。


    假设最短循环节长度为len则原串长度显然为len*k。若只考虑k,并且将k的质因数依次分解,每次试除k,则得到的kk。和len的乘积仍是循环节,利用这个性质。依次用质因数 ii 试除n,若除去后仍是循环节,说明i属于k,将其除去,结果就留下了len。

     【代码】:

     1 #include<cstdio>
     2 #include<bitset>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef unsigned long long ULL ;
     7 const int N = 5e5+10;
     8 ULL h[N],p[N],base = 131;
     9 
    10 char str[N];
    11 int n,m,len,ans,tmp,L,R;
    12 
    13 int prime[N],Min_p[N],cnt;
    14 void Init(){
    15     //memset( is_prime , true , sizeof is_prime );
    16     int tot = 0 ;
    17     for(int i=2;i<N;i++) {
    18         if(!Min_p[i]) {
    19             //if( i < 10 ) printf("%d
    ",i);
    20             prime[++tot]=i;
    21             Min_p[i]=i;
    22         }
    23         for(int j=1;j<=tot;j++) {
    24             if(prime[j]>Min_p[i]||prime[j]*i>N) break;
    25             Min_p[prime[j]*i]=prime[j];
    26         }
    27     }
    28     cnt = tot ;
    29 }
    30 
    31 void get_Hash(){
    32     p[0] = 1;
    33     for(int i=1;i<=len;i++){
    34         p[i] = p[i-1] * base ;
    35         h[i] = h[i-1] * base + (ULL) str[i];
    36     }
    37 }
    38 
    39 bool Vaild( int L , int R , int k ){
    40     return h[R] - h[L+k-1] * p[len-k] == h[L + (len/k-1)*k - 1] - h[L-1] * p[len-k] ;
    41 }
    42 int main()
    43 {
    44     Init();
    45     //for(int i=1;i<10;i++) printf("%d
    ",prime[i]);
    46     scanf("%d%s%d",&n,str+1,&m);
    47 
    48 
    49     len  = strlen( str+1 ) ;
    50     get_Hash();
    51     /*
    52     for(int i=1;i<=len;i++){
    53         printf("%llu
    ",h[i]);
    54     }
    55     */
    56     while( m-- ){
    57         scanf("%d%d",&L,&R);
    58         len = tmp = ans = R - L + 1 ;
    59         while( tmp != 1  ){
    60             int k = Min_p[tmp] ;
    61             while( tmp % k == 0 && Vaild(L,R,ans/Min_p[tmp] ) )
    62                 tmp /= k , ans /= k ;
    63             while( tmp % k == 0 )
    64                 tmp /= k ;
    65         }
    66         printf("%d
    ",ans);
    67     }
    68     return 0 ;
    69 }
  • 相关阅读:
    杭电2083(简易版之最短距离)
    南阳17(单调递增最长子序列)
    杭电1009(FatMouse' Trade)
    Oracle—用户管理的备份(一)
    Retinex processing for automatic image enhancement 翻译
    POJ 1151
    ISO3834认证所需的部分标准
    2013年19个最棒的HTML5网站模板免费下载
    自定义 Preference Header 布局
    [置顶] chinayaosir近10年来所阅读的世界著名IT书籍-图文并茂
  • 原文地址:https://www.cnblogs.com/Osea/p/11324796.html
Copyright © 2020-2023  润新知