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

题目链接: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 }

原文地址:https://www.cnblogs.com/letlifestop/p/10390195.html

时间: 2024-10-27 13:06:49

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

【python-leetcode340-滑动窗口法】至多包含 K 个不同字符的最长子串

问题描述:给定一个字符串s,找到至多包含k个不同字符得最长子串的长度. 比如s="cebea",k=2,那么输出结果就是3,因为此时"ebe"满足条件:至多包含两个不同字符,且子串最长 比如s="world",k=4,那么输出结果就是4,因为"worl"和"orld"满足条件:至多包含4个不同字符,且子串最长 class Solution: def lengthOfLongestSubstringKDist

LeetCode: 3_Longest Substring Without Repeating Characters | 求没有重复字符的最长子串的长度 | Medium

题目: Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest s

需找字符串中重复的最长子串

注意此处说的是重复的最长子串,只要出现重复就好,没说重复的次数. 下面给出的代码是编程珠玑中给出的一种实现. 他是通过后缀数组的方式实现的. #include<stdlib.h> #include<stdio.h> #include<string.h> using namespace std; int comlen(char*p, char*q)//找出公共的最长子串 { int i = 0; if (p == NULL || q == NULL) return 0;

POJ 3294 后缀数组:求不小于k个字符串中的最长子串

思路:先把所有的串连接成一个串,串写串之前用没出现过的字符隔开,然后求后缀:对height数组分组二分求得最长的公共前缀,公共前缀所在的串一定要是不同的,不然就不是所有串的公共前缀了,然后记下下标和长度即可. 刚开始理解错题意,然后不知道怎么写,然后看别人题解也不知道怎么意思,后面看了好久才知道题目意思理解错了. 时间四千多ms,别人才一百多ms,不知道别人怎么做的-- #include<iostream> #include<cstdio> #include<cstring&

【leetcode-03】给定一个字符串,请你找出其中不含有重复字符的最长子串的长度

开个新坑,leetcode上面做题目.下面是题目描述: <!-- 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3. 示例 2: 输入: "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1. 示例 3: 输入: "pwwkew" 输出

leecode-找出其中不含有重复字符的 最长子串 的长度

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度.这道题主要用到思路是:滑动窗口 class Solution { /** * @param String $s * @return Integer */ function lengthOfLongestSubstring($s) { $len = strlen($s); $sarr = str_split($s,1); $varr = array_flip($sarr); $arr = []; $left =0; $mmmm = 0

POJ 3261 Milk Patterns 后缀数组求 一个串种 最长可重复子串重复至少k次

Milk Patterns Description Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some r

POJ 3261 出现至少K次的可重叠最长子串

题意就是给一列数字,求最长的一个子串,并且满足子串在原数串中出现至少K次,子串可以重叠. 解法是将问题转为判定性问题,二分子串的长度,判定是否满足重复至少K次.判定方法是经典的根据子串长度将Height数组分组,看某一分组是否至少含有K个元素. 1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h

[LeetCode] 340. Longest Substring with At Most K Distinct Characters 最多有K个不同字符的最长子串

Given a string, find the length of the longest substring T that contains at most k distinct characters. For example, Given s = “eceba” and k = 2, T is "ece" which its length is 3. 159. Longest Substring with At Most Two Distinct Characters 的拓展,1