题目大意:输入$n$个正整数,($1\leq n\leq 10000$),要求输出最长的连号的长度。(连号指从小到大连续自然数)

题解:考虑从小到大连续自然数差分为$1$,所以可以把原数列差分(后缀自动机不怎么会写啊),查询串为$1,11,111,\dots,111\dots(n-1个1)$,把它们插入到$AC$自动机中,然后查询即可,原数列差分不为$0,1$时赋为$0$(因为不对答案有影响)

卡点:1.原序列差分的数不为$0,1$时会挂。。。

C++ Code:($AC$自动机2018-8-13)

#include <cstdio>
#include <queue>
#define maxn 10010
using namespace std;
int n;
int s[maxn], a[maxn], b[maxn];
int nxt[maxn][2], fail[maxn], cnt[maxn], tot;
int root = 0;
queue<int> q;
void add(int *s, int n) {
int now = root, len = n;
for (int i = 1; i <= len; i++) {
if (nxt[now][s[i]]) now = nxt[now][s[i]];
else now = nxt[now][s[i]] = ++tot;
cnt[now]++;
}
}
void build() {
for (int i = 0; i < 2; i++)
if (nxt[root][i]) fail[nxt[root][i]] = root, q.push(nxt[root][i]);
while (!q.empty()) {
int x = q.front(); q.pop();
for (int i = 0; i < 2; i++) {
if (nxt[x][i]) fail[nxt[x][i]] = nxt[fail[x]][i], q.push(nxt[x][i]);
else nxt[x][i] = nxt[fail[x]][i];
}
}
}
int ask(int *s, int n) {
int now = root, ans = 0, len = n;
for (int i = 1; i <= n; i++) {
if (s[i] > 1 || s[i] < 0) s[i] = 0;
now = nxt[now][s[i]];
for (int j = now; j && ~cnt[j]; j = fail[j]) ans += cnt[j], cnt[j] = -1;
}
return ans;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &s[i]), b[i] = 1;
for (int i = 2; i <= n; i++) a[i - 1] = s[i] - s[i - 1];
add(b, n - 1);
build();
printf("%d\n", ask(a, n - 1) + 1);
return 0;
}

  

题解:当然我们也可以用后缀自动机来做,对差分串建一个后缀自动机,发现若答案长度为$len$,那么长度为$len-1$也是答案,所以可以二分答案(如果你直接求最长的$1$的字段也可以,但我就得这样不是很优美有趣)。

卡点:

C++ Code:

#include <cstdio>
#include <cstring>
#define maxn 20010
using namespace std;
int nxt[maxn][2], fail[maxn], R[maxn], idx;
int last, now, np, p, t, root;
int n, a[maxn];
void insert(int x) {
if (x < 0 || x > 1) x = 0;
R[now = ++idx] = R[p = last] + 1; last = now;
for (; ~p && !nxt[p][x]; p = fail[p]) nxt[p][x] = now;
if (!~p) {fail[now] = root; return ;}
if (R[t = nxt[p][x]] == R[p] + 1) {fail[now] = t; return ;}
R[np = ++idx] = R[p] + 1;
for (int i = 0; i < 2; i++) nxt[np][i] = nxt[t][i];
fail[np] = fail[t]; fail[t] = fail[now] = np;
for (; nxt[p][x] == t; p = fail[p]) nxt[p][x] = np;
}
int tmp[maxn];
bool check(int mid) {
for (int i = 1; i <= mid; i++) tmp[i] = 1;
int now = root;
for (int i = 1; i <= mid; i++) {
now = nxt[now][tmp[i]];
if (!now) return false;
}
return true;
}
int main() {
scanf("%d", &n);
fail[root = 0] = -1; idx = last = 1;
scanf("%d", &a[1]);
for (int i = 2; i <= n; i++) {
scanf("%d", &a[i]);
insert(a[i] - a[i - 1]);
}
int l = 0, r = n, ans = 0;
while (l <= r) {
int mid = l + r >> 1;
if (check(mid)) {
l = mid + 1;
ans = mid;
} else r = mid - 1;
}
printf("%d\n", ans + 1);
}

  

[洛谷P1420]最长连号的更多相关文章

  1. 洛谷 P1420 最长连号【最长合法子序列/断则归一】

    题目描述 输入n个正整数,(1<=n<=10000),要求输出最长的连号的长度.(连号指从小到大连续自然数) 输入输出格式 输入格式: 第一行,一个数n; 第二行,n个正整数,之间用空格隔 ...

  2. 洛谷P1420 最长连号 题解

    题目传送门 这道题我是打暴力的...(尴尬) 所以直接是O(N2)的时间,但好像没有炸,数据很水... #include<bits/stdc++.h> using namespace st ...

  3. P1420 最长连号

    洛谷——P1420 最长连号 题目描述 输入n个正整数,(1<=n<=10000),要求输出最长的连号的长度.(连号指从小到大连续自然数) 输入输出格式 输入格式: 第一行,一个数n; 第 ...

  4. 【洛谷】 P1420 最长连号

    题目描述 输入n个正整数,(1<=n<=10000),要求输出最长的连号的长度.(连号指从小到大连续自然数) 输入输出格式 输入格式: 第一行,一个数n; 第二行,n个正整数,之间用空格隔 ...

  5. 洛谷P1470 最长前缀

    P1470 最长前缀 Longest Prefix 题目描述 在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的.生物学家对于把长的序列分解成较短的序列(即元素)很感兴趣. 如果一个集合 ...

  6. 洛谷P1470 最长前缀 Longest Prefix

    P1470 最长前缀 Longest Prefix 73通过 236提交 题目提供者该用户不存在 标签USACO 难度普及/提高- 提交  讨论  题解 最新讨论 求大神指导,为何错? 题目描述 在生 ...

  7. 洛谷 [p1439] 最长公共子序列 (NlogN)

    可以发现只有当两个序列中都没有重复元素时(1-n的排列)此种优化才是高效的,不然可能很不稳定. 求a[] 与b[]中的LCS 通过记录lis[i]表示a[i]在b[]中的位置,将LCS问题转化为最长上 ...

  8. 洛谷.T22136.最长不下降子序列(01归并排序 分治)

    题目链接 \(Description\) 给定一个长为n的序列,每次可以反转 \([l,r]\) 区间,代价为 \(r-l+1\).要求在\(4*10^6\)代价内使其LIS长度最长,并输出需要操作的 ...

  9. 洛谷P2766 最长递增子序列问题

    https://www.luogu.org/problemnew/show/P2766 注:题目描述有误,本题求的是最长不下降子序列 方案无限多时输出 n 网络流求方案数,长见识了 第一问: DP 同 ...

随机推荐

  1. 如何改变memcached默认的缓存时间?

    我们在使用php的memcached的扩展来对memcached进行数据添加时,数据的有效时间有两种方式.如下图. 至于设置一个UNIX时间戳或      以秒为单位的整数(从当前算起的时间差)来说明 ...

  2. Trie(字典树,前缀树)_模板

    Trie Trie,又经常叫前缀树,字典树等等. Trie,又称前缀树或字典树,用于保存关联数组,其中的键通常是字符串.与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定.一个节点的 ...

  3. Python学习:变量

    变量(Variables): 是为了存储程序在运算过程中的一些中间结果,为了方便日后调用储存在计算的内存中 官方介绍: Variables are used to storeinformation t ...

  4. ruby 比较符号==, ===, eql?, equal?

    “==” 最常见的相等性判断 “==” 使用最频繁,它通常用于对象的值相等性(语义相等)判断,在 Object 的方法定义中,“==” 比较两个对象的 object_id 是否一致,通常子类都会重写覆 ...

  5. 51定时器控制4各led,使用回调函数机制

    程序转载自51hei,经过自己的实际验证,多了一种编程的思路技能,回调函数的基本思想也是基于事件机制的,哪个事件来了, 就执行哪个事件. 程序中,最多四个子定时器,说明51的处理速度是不够的,在中断中 ...

  6. Nodejs模块初始化

    模块初始化 一个模块中的JS代码仅在模块第一次被使用时执行一次,并在执行过程中初始化模块的导出对象.之后,缓存起来的导出对象被重复利用. 主模块 通过命令行参数传递给NodeJS以启动程序的模块被称为 ...

  7. C++代码理解 (强制指针转换)

    #include<iostream> using namespace std; class A { public: A() { a=; b=; c=; f=; } private: int ...

  8. HBase import tsv,csv File

    一,HBase中创建table 表(liupeng:test)并创建 info ,contect 列簇 hbase(main):258:0> create "liupeng:Test& ...

  9. 分支push不上去的问题

    还原一下现场,我在自己的项目里面,从master里面checkout的一个分支,当我在我这个分支里面进行 push代码的操作,我突然发现我的代码不能执行push的操作,如图 这个原因是由于远端的仓库没 ...

  10. 利尔达NB-IOT的PSM和eDRX低功耗模式笔记

    1. NB-IOT的技术优势,广覆盖,NB-IOT与GPRS和LTE相比较,最大链路预算提升了20dB,相当于提升了100倍,即使在地车车库.地下室.地下管道等普通无线网络信号难以到达的地方也容易覆盖 ...