hihocoder 第120周 后缀数组 + 单调队列
来源:互联网 发布:网吧绝地求生优化补丁 编辑:程序博客网 时间:2024/05/15 03:57
分析:
求出高度数组,用单调队列维护区间最小值。高度数组的区间最小值的意义就是这些排名相邻的后缀的最长公共前缀。实际上是把所有字符串划分为后缀。这里的是可重叠子串。
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define pr(x) cout << #x << ": " << x << " " #define pl(x) cout << #x << ": " << x << endl;static const int maxn = int(2e4) + 13;//后缀数组模板,时间复杂度nlogn,空间复杂度nstruct Suffix{ int r[maxn]; //后缀数组,名词数组,高度数组(表示和它前一名后缀的最长前缀长度, 从2开始有意义)。 int sa[maxn],rnk[maxn],height[maxn]; int t[maxn],t2[maxn],c[maxn],n,m; char str[maxn]; //把string转化为r[i] void init_string(string &s) { n = s.size(); for(int i=0;i<n;i++) r[i]=(int)s[i]; m = 128; } void init_char(char *s) { n = strlen(s); for(int i=0;i<n;i++) r[i]=(int)s[i]; m = 128; } int cmp(int *r,int a,int b,int l) { return r[a]==r[b]&&r[a+l]==r[b+l]; } //处理得到后缀数组 void build() { int i,k,p,*x=t,*y=t2; r[n++]=0; for (i=0; i<m; i++) c[i]=0; for (i=0; i<n; i++) c[x[i]=r[i]]++; for (i=1; i<m; i++) c[i]+=c[i-1]; for (i=n-1; i>=0; i--) sa[--c[x[i]]]=i; for (k=1,p=1; k<n; k*=2,m=p) { for (p=0,i=n-k; i<n; i++) y[p++]=i; for (i=0; i<n; i++) if (sa[i]>=k) y[p++]=sa[i]-k; for (i=0; i<m; i++) c[i]=0; for (i=0; i<n; i++) c[x[y[i]]]++; for (i=1; i<m; i++) c[i]+=c[i-1]; for (i=n-1; i>=0; i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for (i=1; i<n; i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?p-1:p++; } n--; } //处理得到高度数组和名次数组 void lcp() { int i, j, k = 0; for (i=1; i <= n; i++) rnk[sa[i]]=i; for (i=0; i < n; i++) { if (k) k--; j = sa[rnk[i] - 1]; while (r[i + k]==r[j + k]) k++; height[rnk[i]] = k; } }};struct jibancanyang{ int que[maxn]; void fun() { int n, k; scanf("%d%d", &n, &k); string str; for (int i = 0; i < n; ++i) { int x; scanf("%d", &x); str += char(x + '0'); } if (k == 1) { printf("%d\n", n); return; } Suffix now; now.init_string(str); now.build(); now.lcp(); int head = 0, tail = 0; int l = 2, r = 2, ans = 0; while (r <= n) { while (r - l < k - 1) { if (r > n) break; int x = now.height[r++]; while (tail != head && x < que[tail - 1]) --tail; que[tail++] = x; } if (r > n) break; ans = max(ans, que[head]); if (que[head] == now.height[l++]) head++; } printf("%d\n", ans); }}ac;int main(){#ifdef LOCAL freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout);#endif ac.fun(); return 0;}
0 0
- hihocoder 第120周 后缀数组 + 单调队列
- poj Common Substrings(后缀数组&单调队列)
- poj 3415 后缀数组+单调队列
- poj3415 Common Substrings (后缀数组+单调队列)
- 【后缀数组+单调队列】省队集训题istring
- 【bzoj1717】Milk Patterns 后缀数组 + (二分||单调队列)
- HDU 6194 string string string :后缀数组+单调队列 | 后缀自动机
- NKOJ 4000 (AHOI 2013)差异(后缀自动机/后缀数组+线段树/单调队列)
- BZOJ3238【后缀数组】【单调栈】
- 017 ACM/ICPC Asia Regional Shenyang Online 1001 后缀数组+单调队列
- pku3261后缀树组+单调队列
- bzoj2806 Cheat 后缀自动机&单调队列
- hihocoder #1084 (后缀数组求模糊匹配)
- 后缀数组 hihocoder 1084 Extend KMP
- hihoCoder 1084 扩展KMP(后缀数组)
- hihoCoder 1403 后缀数组 重复旋律
- 后缀数组 (hihocoder重复旋律系列)
- Common Substrings 后缀数组+单调栈
- 使用Qt获取文件的MD5值
- jni使用过程--初学
- Yarn使用笔记
- 基本知识点
- 原生JS实现document.ready
- hihocoder 第120周 后缀数组 + 单调队列
- 修改linux host name
- [LeetCode]2. Add Two Numbers
- 插件版vim的常用命令
- 安装node.js
- 类似咻一咻,水波纹实现
- node js 的初次谋面
- ThinkPHP中关于CLI的使用方法
- Https通讯原理