bzoj 2806: [Ctsc2012]Cheat
2014-12-06 10:31
423 查看
2806: [Ctsc2012]Cheat
Time Limit: 20 Sec Memory Limit:256 MB
Submit: 481 Solved: 276
[Submit][Status]
Description
Input
第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数
接下来M行的01串,表示标准作文库
接下来N行的01串,表示N篇作文
Output
N行,每行一个整数,表示这篇作文的Lo 值。Sample Input
1 210110
000001110
1011001100
Sample Output
4HINT
输入文件不超过1100000字节注意:题目有改动,可识别的长度不小于90%即可,而不是大于90%
g[i]表示i能向前匹配多长(后缀自动机妥妥的)
f[i]表示以i结尾能匹配多少个字符
二分答案L
f[i] = max(f[j] + i - j) =max(f[j] - j) + i;(i - g[i] + 1<=j <= i - L + 1)
用单调队列优化
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> using namespace std; const int maxn = 1100010; struct Tsam{ struct sanode{ sanode *f, *ch[3]; int l; }pool[maxn * 2], *root, *tail; int tot; void add(int c, int len){ sanode *p = tail, *np = &pool[++ tot]; np->l = len; tail = np; for (; p && !p->ch[c]; p = p->f) p->ch[c] = np; if (!p) np->f = root; else if (p->ch[c]->l == p->l + 1) np->f = p->ch[c]; else{ sanode *q = p->ch[c], *r = &pool[++ tot]; *r = *q; r->l = p->l + 1; q->f = np->f = r; for (; p && p->ch[c] == q; p = p->f) p->ch[c] = r; } } void clear(){ // memset(pool, 0, sizeof(pool)); 去了这句话从1732ms变成了 852ms root = tail = &pool[tot = 1]; } void get_f(char *s, int len, int *f){ sanode *p = root; for (int i = 1, l = 0; i <= len; f[i ++] = l) if (p->ch[s[i] - '0']) l ++, p = p->ch[s[i] - '0']; else{ while (p && !p->ch[s[i] - '0']) p = p->f; if (!p) l = 0; else l = p->l + 1, p = p->ch[s[i] - '0']; } } }sam; int n, m; char ch[maxn]; void init(){ int k = 0; scanf("%d%d", &n, &k); sam.clear(); int tot = 0; for (int i = 1; i <= k; i ++){ scanf("%s", ch + 1); int len = strlen(ch + 1); for (int j = 1; j <= len; j ++) sam.add(ch[j] - '0', ++ tot); sam.add(2, ++ tot); } } int g[maxn], f[maxn], h[maxn]; bool check(int l){ int tt = 0, ww = -1; for (int i = 1; i <= m; i ++){ f[i] = f[i - 1]; if (i - l>= 0){ while (tt <= ww && f[i - l] - (i - l) >= f[h[ww]] - h[ww]) ww --; h[++ ww] = i - l; } while (tt <= ww && h[tt] < i - g[i]) tt ++; if (tt <= ww) f[i] = max(f[i], f[h[tt]] + i - h[tt]); } return f[m] >= m * 0.9 - (1e-9); } void solve(){ sam.get_f(ch, m, g); int tt = 0, ww = m, ans = 0; while (tt <= ww){ int mid = (tt + ww) / 2; if (check(mid)) tt = mid + 1, ans = mid; else ww = mid - 1; } printf("%d\n", ans); } void work(){ for (int i = 1; i <= n; i ++){ scanf("%s", ch + 1); m = strlen(ch + 1); solve(); } } int main(){ init(); work(); return 0; }
相关文章推荐
- [BZOJ2806][CTSC2012]熟悉的文章(Cheat)
- BZOJ 2806: [Ctsc2012]Cheat [广义后缀自动机 单调队列优化DP 二分]
- 【BZOJ2806】[Ctsc2012]Cheat 广义后缀自动机+二分+单调队列优化DP
- [BZOJ2806][Ctsc2012]Cheat(广义后缀自动机+dp)
- 【bzoj2806】[Ctsc2012]Cheat 广义后缀自动机+二分+单调队列优化dp
- [二分 后缀自动机 单调队列优化DP] BZOJ 2806 [Ctsc2012]Cheat
- [BZOJ2806][Ctsc2012][后缀自动机][队列优化][DP]Cheat
- 【bzoj2806】 Ctsc2012—Cheat
- [CTSC 2012][BZOJ 2806]Cheat
- bzoj 2806 [Ctsc2012]Cheat
- [BZOJ2806][Ctsc2012]Cheat(后缀自动机+单调队列优化dp)
- BZOJ 2806: [Ctsc2012]Cheat 后缀自动机+单调队列优化DP
- [BZOJ2806][Ctsc2012]Cheat && 后缀自动机
- BZOJ 2806 (ctsc 2012) Cheat 后缀自动机预处理 + DP
- BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP
- bzoj 2806 [Ctsc2012]Cheat 后缀自动机 单调队列优化dp
- bzoj2806 [Ctsc2012]Cheat(单调队列优化dp+二分+广义SAM)
- [后缀自动机][单调队列优化DP] BZOJ 2806: [Ctsc2012]Cheat
- bzoj 2806: [Ctsc2012]Cheat
- BZOJ.2806.[CTSC2012]Cheat(广义后缀自动机 DP 单调队列)