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

题意就是给一列数字,求最长的一个子串,并且满足子串在原数串中出现至少K次,子串可以重叠。

解法是将问题转为判定性问题,二分子串的长度,判定是否满足重复至少K次。判定方法是经典的根据子串长度将Height数组分组,看某一分组是否至少含有K个元素。

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 #include <string>
 5 #include <string.h>
 6 #include <stdio.h>
 7 #include <queue>
 8 #include <stack>
 9 #include <map>
10 #include <set>
11 #include <cmath>
12 #include <ctime>
13 #include <cassert>
14 #include <sstream>
15 using namespace std;
16
17 const int N=2e6+110;
18
19 int sa[N];
20 int t1[N],t2[N],c[N];
21 int rk[N],height[N];
22
23 inline int cmp(int *r,int a,int b,int l){
24     return r[a]==r[b]&&r[a+l]==r[b+l];
25 }
26 int s[N];
27 void calcSA (int *s,int n,int m) {
28     int i,j,p,*x=t1,*y=t2;
29     for(i=0;i<m;i++)c[i]=0;
30     for(i=0;i<n;i++)c[x[i]=s[i]]++;
31     for(i=1;i<m;i++)c[i]+=c[i-1];
32     for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
33     for(j=1;j<=n;j<<=1){
34         p=0;
35         for(i=n-j;i<n;i++)y[p++]=i;
36         for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; // 排名从小到大,如果pos比j大,则suffix(sa[i]-j)的第二关键字为p
37         for(i=0;i<m;i++)c[i]=0;
38         for(i=0;i<n;i++)c[x[y[i]]]++;
39         for(i=1;i<m;i++)c[i]+=c[i-1];
40         for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; // 根据第二关键字从大到小,确定新一轮sa
41         swap(x,y);
42         p=1;x[sa[0]]=0;
43         for(i=1;i<n;i++)
44             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
45         if(p>=n)break;
46         m=p;
47     }
48 }
49
50 void calcHeight(int *s,int n) {
51     int i,j,k=0;
52     for(i=0;i<=n;i++)rk[sa[i]]=i;
53     for(i=0;i<n;i++){
54         if(k)k--; // h[i]>=h[i-1]-1
55         j=sa[rk[i]-1]; // suffix(j)排名在suffix(i)前一位
56         while(s[i+k]==s[j+k])k++; // 暴力计算lcp
57         height[rk[i]]=k;
58     }
59 }
60
61
62 bool ok(int n,int m,int k) {
63     int cnt=1;
64     for (int i=1;i<=n;i++) {
65         if (height[i]<m) {
66             cnt=1;
67         }
68         else {
69             cnt++;
70             if (cnt>=k) return true;
71         }
72     }
73     return false;
74 }
75 int main () {
76     int n,k;
77     while (scanf("%d %d",&n,&k)!=EOF) {
78         int mx=0;
79         for (int i=0;i<n;i++) {
80             scanf("%d",s+i);
81             mx=max(mx,s[i]);
82         }
83         s[n]=0;
84         calcSA(s,n+1,mx+10);
85         calcHeight(s,n);
86         int l=0,r=n,ret=0;
87         while (l<=r) {
88             int m=(l+r)>>1;
89             if (ok(n,m,k)) {
90                 ret=m;
91                 l=m+1;
92             }
93             else r=m-1;
94         }
95         cout<<ret<<endl;
96     }
97     return 0;
98 }
时间: 2024-10-10 01:20:02

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

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

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

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

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

[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

395 Longest Substring with At Least K Repeating Characters 至少有K个重复字符的最长子串

找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k .输出 T 的长度.示例 1:输入:s = "aaabb", k = 3输出:3最长子串为 "aaa" ,其中 'a' 重复了 3 次.示例 2:输入:s = "ababbc", k = 2输出:5最长子串为 "ababb" ,其中 'a' 重复了 2 次, 'b' 重复了 3 次. 详见:https://leetcode.com

leetcode 395 至少有K个重复字符的最长子串

找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k .输出 T 的长度. 示例 1: 输入: s = "aaabb", k = 3 输出: 3 最长子串为 "aaa" ,其中 'a' 重复了 3 次. 示例 2: 输入: s = "ababbc", k = 2 输出: 5 最长子串为 "ababb" ,其中 'a' 重复了 2 次, 'b' 重复了 3 次. 思路1: 暴力枚举 c

POJ - 3261 Milk Patterns (后缀数组求可重叠的 k 次最长重复子串)

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 regular pattern

【POJ 3294】Life Forms 不小于k个字符串中的最长子串

一下午和一晚上都在刚这道题,各种错误都集齐了so sad 我的时间啊!!! 后缀数组就先做到这里吧,是在伤不起啊QAQ 出现了各种奇怪的错误,看了标算,然后乱改自己的代码,莫名其妙的改A了,后来发现用字符直接给int赋值会WA,必须一个字符先给另一个字符赋值,后者再给int赋值就能A(什么鬼).后来加了一个(int)s[n]强制转换就简单地A了,评测时强制转换睡觉了吗?还是我rp太差,得多攒点rp #include<cstdio> #include<cstring> #includ

POJ - 1743 Musical Theme (后缀数组求不可重叠最长重复子串)

Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the piano. It is unfortunate but true that this representation of melodies ignores the notion of music

[LeetCode] 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. 这道题是之前那道Longest Substring with At Most Two Distinct Characters的拓展