询问子串的最小循环节

论文题:Efficient data structures for the factor periodicity problem.

#include #include #include #include #include #include #include  #include #include #include using namespace std; #define N 200002 #define M 2000010 #define ULL unsigned long long #define LL long long #define ls (i << 1) #define rs (ls | 1) #define md ((ll + rr) >> 1) #define lson ll, md, ls #define rson md + 1, rr, rs #define inf 0x3f3f3f3f #define eps 1e-4 #define pii pair#define MP make_pair #define mod 1000000007 char s[N]; int n; int sa[N], wa[N], wb[N], wv[N], wc[N]; int lg[N]; int lab[N][22]; int lab_cnt; struct Arith { int a, b, d; Arith(int a = -1, int d = -1, int b = -1) : a(a), d(d), b(b) {}; void init(int v) { a = b = v; d = -1; } void upd(int v) { if(a == -1) a = v; else if(d == -1) d = v - a; b = v; } int get_min(int p) { /* >= p */ if(a == -1) return inf; if(a >= p) return a; if(d == -1) return inf; if(b < p) return inf; int k = ceil((p-a+0.0) / d); return min(b, a + k * d); } int get_max(int p) { /* <= p */ if(a == -1) return -1; if(a > p) return -1; if(d == -1) return a; int k = (p-a) / d; return min(b, a + k * d); } Arith inv_cut(int val) {/* val - this */ if(a == -1) return *this; int t = a; a = val-b; b = val-t; return *this; } Arith add(int val) { /* val + this */ if(a == -1) return *this; a += val; b += val; return *this; } }; Arith merge2(Arith x, Arith y) { Arith ans; for(int i = x.a; i != -1 && x.a <= i && i <= x.b; i += x.d) { if(y.a <= i && i <= y.b && (y.d == -1 || (i-y.a) % y.d == 0)) ans.upd(i); } return ans; } Arith merge(Arith x, Arith y) { if(x.d == -1 || x.a + x.d == x.b) return merge2(x, y); else if(y.d == -1 || y.a + y.d == y.b) return merge2(y, x); else { if(x.d != y.d) return Arith(); if(x.a > y.a) swap(x, y); if(y.a > x.b) return Arith(); if((y.a-x.a)%x.d == 0) return Arith(y.a, min(y.b, x.b) == y.a ? -1 : x.d, min(y.b, x.b)); } return Arith(); } LL get_hx(int id, int j) { if(j < 0) return -1; return (LL)id * (n+1) + j; } struct Hash { const static int hxsz = 2333333; int fst[hxsz], nxt[N*22], e; LL state[N*22]; Arith val[N*22]; void init() { memset(fst, -1, sizeof fst); e = 0; } void insert(LL st, int v) { int u = st % hxsz; for(int i = fst[u]; ~i; i = nxt[i]) { if(state[i] == st) { val[i].upd(v); return ; } } state[e] = st; val[e].init(v); nxt[e] = fst[u]; fst[u] = e++; } Arith query(LL st) { if(st < 0) return Arith(); int u = st%hxsz; for(int i = fst[u];~i; i = nxt[i]) { if(state[i] == st) return val[i]; } return Arith(); } }hm; void init() { for(int i = 1, k = 0; i < N; i <<= 1, k++) lg[i] = k; hm.init(); lab_cnt = 0; } bool cmp(int *r, int a, int b, int l) { return r[a] == r[b] && r[a+l] == r[b+l]; } void da(char *r, int n, int m) { int i, j, k, p, *x = wa, *y = wb; for(i = 0; i < m; ++i) wc[i] = 0; for(i = 0; i < n; ++i) ++wc[x[i] = r[i]]; for(i = 1; i < m; ++i) wc[i] += wc[i-1]; for(i = n-1; i >= 0; --i) sa[--wc[x[i]]] = i; for(i = 0; i < n; ++i) { if(i == 0 || x[sa[i-1]] != x[sa[i]]) ++lab_cnt; lab[sa[i]][0] = lab_cnt; hm.insert(get_hx(lab_cnt, sa[i]), sa[i]); } for(j = 1, p = 1, k = 1; p < n; m = p, j <<= 1, k++) { for(i = n-j, p = 0; i < n; ++i) y[p++] = i; for(i = 0; i < n; ++i) if(sa[i] >= j) y[p++] = sa[i] - j; for(i = 0; i < n; ++i) wv[i] = x[y[i]]; for(i = 0; i < m; ++i) wc[i] = 0; for(i = 0; i < n; ++i) ++wc[wv[i]]; for(i = 1; i < m; ++i) wc[i] += wc[i-1]; for(i = n-1; i >= 0; --i) sa[--wc[wv[i]]] = y[i]; swap(x, y); for(x[sa[0]] = 0, p = 1, i = 1; i < n; ++i) x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++; for(i = 0; i < n; ++i) { if(i == 0 || x[sa[i-1]] != x[sa[i]]) ++lab_cnt; lab[sa[i]][k] = lab_cnt; hm.insert(get_hx(lab_cnt, sa[i]/(j<<1)), sa[i]); } } for(; j <= n; j <<= 1, k++) for(i = 0; i < n; ++i) lab[i][k] = lab[i][k-1]; } int succ(int q, int p, int len) { int id = lab[p][lg[len]]; int k = q/len; Arith s1 = hm.query(get_hx(id, k)); Arith s2 = hm.query(get_hx(id, k+1)); int mi = min(s1.get_min(q), s2.get_min(q)); //printf("succ(%d, %d, %d) mi %d\n", q, p, len, mi); if(mi <= q + len) return mi; else return inf; } int pred(int q, int p, int len) { int id = lab[p][lg[len]]; int k = q/len; Arith s1 = hm.query(get_hx(id, k)); Arith s2 = hm.query(get_hx(id, k-1)); int mx = max(s1.get_max(q), s2.get_max(q)); //printf("pred(%d, %d, %d), mx %d\n", q, p, len, mx); if(mx >= q-len) return mx; return -1; } Arith occ(int p1, int len1, int p2, int len2) { //printf("occ [%d,%d], [%d,%d]\n", p1, p1+len1-1, p2, p2 + len2 -1); int p = succ(p2, p1, len1); int pos = p2 + len2 - 1 - len1 + 1; if(p > pos) return Arith(); int q = succ(p+1, p1,len1); if(q > pos) return Arith(p, -1, p); int d = q - p; int t = pred(pos, p1, len1); //printf("occ (%d,%d,%d)\n", p, d, t); puts(""); return Arith(p, d, t); } int largePS(int l, int r, int len) { if(len == 1) return s[l] == s[r] ? 1 : 0; int d = len >> 1; Arith s1 = occ(l, d, r-len+1, len).inv_cut(r+1); Arith s2 = occ(r-d+1, d, l, len).add(d-l); //printf("largePS(%d) s1(%d, %d, %d) s2(%d, %d, %d)\n", len,s1.a, s1.d, s1.b, s2.a, s2.d, s2.b); s1 = merge(s1,s2); //printf("merge (%d, %d, %d)\n", s1.a, s1.d, s1.b); puts(""); return s1.b; } int larger(int l, int r, int k) { if(k == 0) return 0; int d1 = succ(l+1, l, k); if(d1 == inf) return -1; d1 -= l; int d2 = pred(r-k, r-k+1, k); if(d2 == inf) return -1; d2 = r-d2+1 - k; //printf("larger(%d,%d,%d) d1 %d d2 %d\n", l, r,k,d1, d2); puts(""); return d1 == d2 ? r-l+1-d1 : -1; } int query(int l, int r) { int ans = 0; int i; for(i = 1; i < r-l+1; i <<= 1) { ans = max(ans, largePS(l, r, i)); //printf("ans %d %d\n", ans, i); } ans = max(ans, larger(l, r, i>>1)); return r-l+1 - ans; } int gao(int l, int r) { static char t[N]; static int fail[N]; int m = r - l + 1; for(int i = 0; i < m; ++i) t[i] = s[l+i]; fail[0] = -1; int i = 1, j = 0; while(i < m) { if(j < 0 || t[j] == t[i]) { ++j, ++i; fail[i] = j; } else j = fail[j]; } return m - fail[m]; } int getin() { char c; while((c=getchar()) && !('0' <= c && c <= '9')); int ans = c - '0'; while((c=getchar()) && '0' <= c&& c<= '9') ans = ans*10 + c-'0'; return ans; } int main() { int T; scanf("%d", &T); int cas = 1; while(T--) { init(); scanf("%s", s); n = strlen(s); da(s, n+1, 130); int m; m = getin(); printf("Case #%d:\n", cas++); while(m--) { int l, r; l = getin(); r = getin(); --l, --r; int ret = query(l, r); printf("%d\n", ret); } } }

hdu 5814 Find the Period相关推荐

  1. ajax请求必须打断点才能成功,Jquery等待ajax执行完毕继续执行(断点调试正常,运行异常)...

    以前写过一个程序,发现用断点调试的时候,一步步的运行,程序是可以的,但是去了断点程序就出现了问题. $(document).ready(function(){ var arra=new Array() ...

  2. c语言无法打开源文件stdafx.h,vs2010 中无法打开 源文件 stdafx.h 未定义标识符 “xxx”...

    HDU 1231 (13.12.2) Problem Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj ...

  3. HDU 5908 Abelian Period 暴力

    Abelian Period 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5908 Description Let S be a number st ...

  4. HDU - 1358 Period(KMP的next数组求最小循环节)

    题目链接:点击查看 题目大意:给出一个长度为n的字符串,问有哪些前缀是周期性字符串 题目分析:因为n给的很大,所以肯定不能暴力判断了,我们可以巧妙的利用kmp的next数组进行判断,next数组有一个 ...

  5. HDU 1358 Period KMP

    题意:求一个字符串的所有前缀是否是复制出来的. 解题思路:next 数值判断即可 解题代码: 1 // File Name: getnext.cpp 2 // Author: darkdream 3 ...

  6. hdu 1358 Period

    枚举长度判断是否符合周期串,用next判断 #include<cstring> #include<cstdio> using namespace std; #define MA ...

  7. hdu 1358 Period (KMP求循环次数)

    Problem - 1358 KMP求循环节次数.题意是,给出一个长度为n的字符串,要求求出循环节数大于1的所有前缀.可以直接用KMP的方法判断是否有完整的k个循环节,同时计算出当前前缀的循环节的个数 ...

  8. HDU 5861 Road 线段树区间更新单点查询

    题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5861 Road Time Limit: 12000/6000 MS (Java/Othe ...

  9. hdu 过山车_从机械工程师到软件开发人员–我的编码过山车

    hdu 过山车 There aren't many people out there who grew up dreaming of writing code. I definitely didn't ...

最新文章

  1. 16位代码段与32位代码段的区别
  2. Docker selenium自动化 - windows版docker的安装与运行环境检测
  3. php 验证 e mail,PHP 表单验证 - 验证 E-mail 和 URL
  4. PAT1048 数字加密 (20 分)
  5. Android学习笔记---SQLite介绍,以及使用Sqlite,进行数据库的创建,完成数据添删改查的理解
  6. python模块datetime_Python模块-datetime
  7. Java Greedy Snake, need to be updated
  8. SpringBoot学习(三)YAML语法、JSR303校验、多环境开发切换
  9. 2021-09-13 QCC3003 回连
  10. JDK1.8和JRE文件结构
  11. ShuipFCMS -- 简单强大内容管理系统
  12. 如何一次性下载全国谷歌卫星影像地图数据
  13. 辅助功能 AccessibilityService笔记
  14. 易语言API获取进程程序路径
  15. 我的无线宽带由器 TP-LINK TL-WR841N如何设置限
  16. 单片机教学打铃控制器C语言
  17. Java中访问修饰符public、private、protect、default访问范围
  18. SAP ABAP Odata
  19. J2SE、J2EE、J2ME
  20. 小伙失恋服毒后又反悔 自作聪明喝洗衣粉洗胃

热门文章

  1. C#一个完整的Log4net使用实例
  2. office 论文 页码_毕业论文必备技巧:Word页码从第三页开始设置方法
  3. 我在拓展训练中得到的感悟
  4. 周周过,周周结(十九)
  5. 周周过,周周结(6)
  6. 重生之我要学C++第四天
  7. Linux和Win常用分卷压缩和合并压缩方法(主要Linux)
  8. php fgetc()函数视频,PHP中的fgetc()函数
  9. Python自助爬虫代理ip模块
  10. 横滨中文离线地图App上线