ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

D - Milk Patterns (出现k次可重复的最长子串的长度)

2019-02-17 09:51:38  阅读:225  来源: 互联网

标签:子串 return int mid Patterns maxn ans include Milk


题目链接:https://cn.vjudge.net/contest/283743#problem/D

题目大意:给你n个数,然后问你出现m次的最长子串的长度。

具体思路:和上一篇博客的内容差不多,这个是可重复的,就不需要考虑sa的问题了,每一次还是二分答案,判断出现的最长前缀就可以了。注意二分的时候,每一次的寻找,初始值为1,因为这个字符串就已经出现过一次了。

AC代码:

  1 #include<iostream>
  2 #include<stack>
  3 #include<cstring>
  4 #include<iomanip>
  5 #include<stdio.h>
  6 #include<algorithm>
  7 #include<cmath>
  8 using namespace std;
  9 # define ll long long
 10 # define inf 0x3f3f3f3f
 11 const int maxn = 5e6+100;
 12 int cntA[maxn], cntB[maxn], sa[maxn], tsa[maxn], A[maxn], B[maxn], height[maxn];
 13 int Rank[maxn];
 14 int ch[maxn];
 15 int sto[maxn];
 16 ll n,m;
 17 //sa[i]代表第i小的后缀位置,Rank[i]代表第i位置的后缀,排名第几小
 18 // height[i]代表排名第i个字符串和第i-1个字符串的相同前缀有多少个
 19 void cal(int maxx)
 20 {
 21     for(int i = 0; i <=maxx; i++)
 22         cntA[i] = 0;
 23     //   cout<<1<<endl;
 24     //  cout<<n<<endl;
 25     for(int i = 1; i <= n; i++)
 26     {
 27         //cout<<ch[i-1]<<endl;
 28         cntA[ch[i-1]]++;
 29     }
 30     //  cout<<1<<endl;
 31     for(int i = 1; i <= maxx; i++)
 32         cntA[i] += cntA[i-1];
 33     for(int i = n; i; i--)
 34         sa[cntA[ch[i-1]]--] = i;
 35     Rank[sa[1]] = 1;
 36     for(int i = 2; i <= n; i++)
 37     {
 38         Rank[sa[i]] = Rank[sa[i-1]];
 39         if(ch[sa[i]-1] != ch[sa[i-1]-1])
 40             Rank[sa[i]]++;
 41     }
 42     for(int l = 1; Rank[sa[n]] < n; l <<= 1)
 43     {
 44         memset(cntA, 0, sizeof(cntA));
 45         memset(cntB, 0, sizeof(cntB));
 46         for(int i = 1; i <= n; i++)
 47         {
 48             cntA[A[i] = Rank[i]]++;
 49             cntB[B[i] = (i+l <= n)?Rank[i+l]:0]++;
 50         }
 51         for(int i = 1; i <= n; i++)
 52             cntB[i] += cntB[i-1];
 53         for(int i = n; i; i--)
 54             tsa[cntB[B[i]]--] = i;
 55         for(int i = 1; i <= n; i++)
 56             cntA[i] += cntA[i-1];
 57         for(int i = n; i; i--)
 58             sa[cntA[A[tsa[i]]]--] = tsa[i];
 59         Rank[sa[1]]=1;
 60         for(int i = 2; i <= n; i++)
 61         {
 62             Rank[sa[i]] = Rank[sa[i-1]];
 63             if(A[sa[i]] != A[sa[i-1]] || B[sa[i]] != B[sa[i-1]])
 64                 Rank[sa[i]]++;
 65         }
 66     }
 67     for(int i = 1, j = 0; i <= n; i++)
 68     {
 69         if(j)
 70             j--;
 71         while(ch[i+j-1] == ch[sa[Rank[i]-1] + j - 1])
 72             j++;
 73         height[Rank[i]] = j;
 74     }
 75 }
 76 bool judge(int t)
 77 {
 78     int ans=1;
 79     for(int i=2; i<=n; i++)
 80     {
 81         if(height[i]>=t)
 82         {
 83             ans++;
 84         }
 85         else
 86         {
 87             ans=1;
 88         }
 89         if(ans>=m)
 90             return true;
 91     }
 92     return false;
 93 }
 94 int main()
 95 {
 96     int maxx=0;
 97     scanf("%lld %lld",&n,&m);
 98     for(int i=1; i<=n; i++)
 99     {
100         scanf("%d",&ch[i]);
101         maxx=max(maxx,ch[i]);
102     }
103     cal(maxx);
104     int l=0,r=1e8,ans=0;
105     while(l<=r)
106     {
107         int mid=(l+r)>>1;
108         if(judge(mid))
109         {
110             ans=mid;
111             l=mid+1;
112         }
113         else
114         {
115             r=mid-1;
116         }
117     }
118     printf("%d\n",ans);
119     return 0;
120 }

 

标签:子串,return,int,mid,Patterns,maxn,ans,include,Milk
来源: https://www.cnblogs.com/letlifestop/p/10390195.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有