hihocoder 1419 重复旋律4

描述

小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为长度为 N 的数构成的数列。小Hi在练习过很多曲子以后发现很多作品中的旋律有重复的部分。

我们把一段旋律称为(k,l)-重复的,如果它满足由一个长度为l的字符串重复了k次组成。 如旋律abaabaabaaba是(4,3)重复的,因为它由aba重复4次组成。

小Hi想知道一部作品中k最大的(k,l)-重复旋律。

解题方法提示

输入

一行一个仅包含小写字母的字符串。字符串长度不超过 100000。

输出

一行一个整数,表示答案k。

Sample Input
babbabaabaabaabab
Sample Output
4
假如循环节长度为L
如果求出了后缀i和i+L的lcp
那么重复次数k=lcp(i,i+L)/L+1
那么O(n^2)的暴力有了,枚举L和i,计算k更新最大值
但是枚举i可以只枚举L的倍数,算出k
对于i和i+L,最多只会相差1
如果最优串的开始位置恰好在L的倍数上,那我们找到的最大的k就是正确答案
如果不在L的倍数上,那么最优的开始位置肯定在(i-L,i)上
如果lcp模L有余数,说明前面还需要补上L-lcp%L位,如果可行答案可以加1
于是可以判断开始位置为i-L+lcp%L与i+lcp%L的lcp
如果构成重复,那么算出来的
k=lcp(i-L+lcp%L,i+lcp%L)/L+1=[lcp(i,i+L)/L+1]+1,比开始位置为i要好
于是复杂度:
$O(\frac{n}{1}+\frac{n}{2}+\frac{n}{3}+...\frac{n}{n})$
$=O(nlogn)$
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 int n,m,c[200001],x[200001],y[200001],SA[200001],s[200001],rk[200001],h[200001];
 8 int Min[200001][21],Log[200001],ans;
 9 char ch[200001];
10 void radix_sort()
11 {int i;
12   for (i=0;i<=m;i++)
13     c[i]=0;
14   for (i=1;i<=n;i++)
15     c[x[y[i]]]++;
16   for (i=2;i<=m;i++)
17     c[i]+=c[i-1];
18   for (i=n;i>=1;i--)
19     SA[c[x[y[i]]]--]=y[i];
20 }
21 void build_SA()
22 {int i,j,k,p;
23   for (i=1;i<=n;i++)
24     x[i]=s[i],y[i]=i;
25   m=100000;
26   radix_sort();
27   for (k=1;k<=n;k<<=1)
28     {
29       p=0;
30       for (i=n-k+1;i<=n;i++)
31     y[++p]=i;
32       for (i=1;i<=n;i++)
33     if (SA[i]>k) y[++p]=SA[i]-k;
34       radix_sort();
35       p=1;swap(x,y);
36       x[SA[1]]=1;
37       for (i=2;i<=n;i++)
38     x[SA[i]]=((y[SA[i]]==y[SA[i-1]])&&(y[SA[i]+k]==y[SA[i-1]+k]))?p:++p;
39       if (p>=n) break;
40       m=p;
41     }
42   for (i=1;i<=n;i++)
43     rk[SA[i]]=i;
44   int L=0;
45   for (i=1;i<=n;i++)
46     {
47       if (L>0) L--;
48       j=SA[rk[i]-1];
49       while (i+L<=n&&j+L<=n&&(s[j+L]==s[i+L])) L++;
50       h[rk[i]]=L;
51     }
52 }
53 int rmq(int x,int y)
54 {
55   int L=Log[y-x+1];
56   return min(Min[x][L],Min[y-(1<<L)+1][L]);
57 }
58 int lcp(int x,int y)
59 {
60   if (rk[x]>rk[y]) swap(x,y);
61   return rmq(rk[x]+1,rk[y]);
62 }
63 int main()
64 {int i,j,L;
65   scanf("%s",ch);
66   n=strlen(ch);
67   for (i=1;i<=n;i++)
68     {
69       s[i]=ch[i-1]-‘a‘+1;
70     }
71   build_SA();
72   memset(Min,127/2,sizeof(Min));
73   for (i=1;i<=n;i++)
74     Min[i][0]=h[i];
75   Log[1]=0;
76   for (i=2;i<=n;i++)
77     Log[i]=Log[i/2]+1;
78   for (j=1;(1<<j)<=n;j++)
79     {
80       for (i=1;i<=n-(1<<j)+1;i++)
81     Min[i][j]=min(Min[i][j-1],Min[i+(1<<j-1)][j-1]);
82     }
83   for (L=1;L<=n;L++)
84     {
85       for (i=1;i+L<=n;i+=L)
86     {
87       int p=lcp(i,i+L);
88       ans=max(ans,p/L+1);
89       if (i-L+p%L>=1)
90         {
91           ans=max(ans,lcp(i-L+p%L,i+p%L)/L+1);
92         }
93     }
94     }
95   printf("%d\n",ans);
96 }

原文地址:https://www.cnblogs.com/Y-E-T-I/p/8514661.html

时间: 2024-11-03 03:30:07

hihocoder 1419 重复旋律4的相关文章

【简要题解】Hihocoder 重复旋律1-8简要题解

[简要题解]Hihocoder 重复旋律1-8简要题解 编号 名称标签 难度 1403 后缀数组一·重复旋律 Lv.4 1407 后缀数组二·重复旋律2 Lv.4 1415 后缀数组三·重复旋律3 Lv.4 1419 后缀数组四·重复旋律4 Lv.4 1445 后缀自动机二·重复旋律5 Lv.4 1449 后缀自动机三·重复旋律6 Lv.4 1457 后缀自动机四·重复旋律7 Lv.1 1465 后缀自动机五·重复旋律8 Lv.1 1466 后缀自动机六·重复旋律9 Lv.1 后缀数组 思路简单

hihoCoder 后缀数组 重复旋律

#1403 : 后缀数组一·重复旋律 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列. 小Hi在练习过很多曲子以后发现很多作品自身包含一样的旋律.旋律是一段连续的数列,相似的旋律在原数列可重叠.比如在1 2 3 2 3 2 1 中 2 3 2 出现了两次. 小Hi想知道一段旋律中出现次数至少为K次的旋律最长是多少? 解题方法提示 输入 第一行两个整数 N和K.1≤N≤2000

后缀数组之hihocoder 重复旋律1-4

蒟蒻知道今天才会打后缀数组,而且还是nlogn^2的...但基本上还是跑得过的: 重复旋律1: 二分答案,把height划分集合,height<mid就重新划分,这样保证了每个集合中的LCP>=mid,套路板子题 // MADE BY QT666 #include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #include<cstring> using

hihocoder #1407 : 后缀数组二&#183;重复旋律2

#1407 : 后缀数组二·重复旋律2 Time Limit:5000ms Case Time Limit:1000ms Memory Limit:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列.小Hi在练习过很多曲子以后发现很多作品自身包含一样的旋律. 旋律可以表示为一段连续的数列,相似的旋律在原数列不可重叠,比如在1 2 3 2 3 2 1 中 2 3 2 出现了一次,2 3 出现了两次,小Hi想知道一段旋律中出现次数至少为两次

hihocoder #1449 : 后缀自动机三&#183;重复旋律6

#1449 : 后缀自动机三·重复旋律6 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi想知道一部作品中所有长度为K的旋律中出现次数最多的旋律的出现次数.但是K不是固定的,小Hi想知道对于所有的K的答案. 解题方法提示 × 解题方法提示 小Hi:上次我们已经学习了后缀自动机了,今天我们再来解决一个用到后缀自动机的问题. 小Ho:好!那我们开始吧! 小Hi:现在我们要对K

hihocoder #1457 : 后缀自动机四&#183;重复旋律7

#1457 : 后缀自动机四·重复旋律7 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 神奇的是小Hi发现了一部名字叫<十进制进行曲大全>的作品集,顾名思义,这部作品集里有许多作品,但是所有的作品有一个共同特征:只用了十个音符,所有的音符都表示成0-9的数字. 现在小Hi想知道这部作品中所有不同的旋律的“和”(也就是把串看成数字,在十进制下的求和,允许有前导0).答案有可能

hihocoder #1465 : 后缀自动机五&#183;重复旋律8

#1465 : 后缀自动机五·重复旋律8 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 小Hi发现旋律可以循环,每次把一段旋律里面最前面一个音换到最后面就成为了原旋律的“循环相似旋律”,还可以对“循环相似旋律”进行相同的变换能继续得到原串的“循环相似旋律”. 小Hi对此产生了浓厚的兴趣,他有若干段旋律,和一部音乐作品.对于每一段旋律,他想知道有多少在音乐作品中的子串(重复便多

hihocoder #1415 : 后缀数组三&#183;重复旋律3

#1415 : 后缀数组三·重复旋律3 Time Limit:5000ms Case Time Limit:1000ms Memory Limit:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列.小Hi在练习过很多曲子以后发现很多作品中的旋律有共同的部分. 旋律是一段连续的数列,如果同一段旋律在作品A和作品B中同时出现过,这段旋律就是A和B共同的部分,比如在abab 在 bababab 和 cabacababc 中都出现过.小Hi想

hihoCoder 后缀自动机三&#183;重复旋律6

后缀自动机三·重复旋律6 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi想知道一部作品中所有长度为K的旋律中出现次数最多的旋律的出现次数.但是K不是固定的,小Hi想知道对于所有的K的答案. 解题方法提示 输入 共一行,包含一个由小写字母构成的字符串S.字符串长度不超过 1000000. 输出 共Length(S)行,每行一个整数,表示答案. 样例输入 aab 样例输出