hihocoder #1419 : 后缀数组四·重复旋律4

http://hihocoder.com/problemset/problem/1419

这个题可以用类似https://www.cnblogs.com/hehe54321/p/8808226.html的方法A掉,分析比题解要简单...(应该吧?)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 typedef long long LL;
 7 typedef unsigned long long ULL;
 8 char s[100010];
 9 LL n,anss;
10 ULL powx[100100],hs[100100];
11 const ULL X=131;
12 ULL ghash(LL x,LL y)//[x,y]的哈希
13 {
14     return hs[x]-hs[y+1]*powx[y-x+1];
15 }
16 LL lcp(LL x,LL y)//后缀x和后缀y的lcp
17 {
18     if(x>n||y>n)    return 0;
19     LL l=0,r=min(n-x+1,n-y+1)+1,mid;
20     while(r-l>1)
21     {
22         mid=l+(r-l)/2;
23         if(ghash(x,x+mid-1)==ghash(y,y+mid-1))    l=mid;
24         else    r=mid;
25     }
26     return l;
27 }
28 LL lcs(LL x,LL y)//前缀x和前缀y的lcs
29 {
30     if(!x||!y)    return 0;
31     LL l=0,r=min(x,y)+1,mid;
32     while(r-l>1)
33     {
34         mid=l+(r-l)/2;
35         if(ghash(x-mid+1,x)==ghash(y-mid+1,y))    l=mid;
36         else    r=mid;
37     }
38     return l;
39 }
40 LL ans;
41 int main()
42 {
43     LL i,j,b,l,r,k;
44     scanf("%s",s+1);n=strlen(s+1);
45     powx[0]=1;
46     for(i=1;i<=100000;i++)    powx[i]=powx[i-1]*X;
47     for(i=n;i>=1;i--)    hs[i]=hs[i+1]*X+s[i];
48     for(i=1;i<=n;i++)
49     {
50         b=n/i;
51         for(j=1,k=0;j<=b;j++)
52         {
53             for(;k<b&&ghash(i*(j-1)+1,i*j)==ghash(i*k+1,i*(k+1));k++);
54             //例如对于dba,bca,bca,bde
55             //当i=3,j=2时,k=3
56             l=min(i-1,lcs(i*(j-1),i*k));r=min(i-1,lcp(i*(j-1)+1,i*k+1));
57             //此时l=1,r=1
58             ans=max(ans,k-j+1);
59             //此时只可能分成两段的倍数,且长度为k-j+1
60             //又例如:当i=3,j=3,k=3时
61             //l=2,r=1
62             //k-j+1=1,因此没有需要统计的
63             if(l+r>=i)    ans=max(ans,k-j+2);
64             //但事实上有cabcab没有统计
65             //可以证明,像这种情况漏统计的串的循环次数最多比k-j+1大1
66             //漏统计的数量是从第i*(j-1)-l+1位开始的到第i*(j-1)+r-i+1位开始的
67             //共出现r+l-i+1次,每一次均循环k-j+2次
68             //显然只有当r+l-i+1大于0时才会有此情况
69             //又例如:例如ac,cc,c,当i=2,j=2,k=2,l=1,r=1时
70             //此时还有cccc被漏统计
71             //从第2位开始,到第2位结束,重复2次
72         }
73     }
74     printf("%lld",ans);
75     return 0;
76 }
posted @ 2018-04-12 15:58  hehe_54321  阅读(143)  评论(0编辑  收藏  举报
AmazingCounters.com