题目大意:输入$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. redis之cluster(集群)

    搭建redis cluster 1. 准备节点 2. 节点间的通信 3. 分配槽位给节点 redis-cluster架构 多个服务端,负责读写,彼此通信,redis指定了16384个槽. 多匹马儿,负 ...

  2. Python3 函数return

    # def logger(): # f = open("loge.txt","a") # f.write("2017-09-15 exec funct ...

  3. shell重温---基础篇(连接数据库)

    前几天分享了shell字符串操作,数组操作等,接下来回归到项目,进行数据库操作.按照一般情况来说,shell连接数据库基本上都是DB使用的,因为需要运行大量的sql啊什么的,所以都会封装到shell中 ...

  4. Android面试收集录 Android系统的资源+其他

    1.Android应用程序的资源是如何存储的,如何使用? res文件夹或者assets文件夹 res目录中的资源在R类中生成一个int变量,然后再布局文件中可以直接使用,在代码中,要getResour ...

  5. struts2官方 中文教程 系列八:异常处理

    在本教程中,我们将探讨如何启用Struts 2框架处理web应用程序生成的任何未捕获的异常.Struts 2提供了健壮的异常处理,包括能够自动记录任何未捕获的异常,并将用户重定向到错误web页面. 贴 ...

  6. 1139: [POI2009]Wie

    1139: [POI2009]Wie https://www.lydsy.com/JudgeOnline/problem.php?id=1139 分析: Dijkstra.状压最短路,dis[i][j ...

  7. 程序员编程利器:20款最好的免费的IDEs和编辑器

    程序员编程利器:20款最好的免费的IDEs和编辑器 还没转眼明年可就大年三十了,忙的可真是晕头转了个向,看着亲朋好友们那让人欣羡的小肚腩,不禁感慨,岁月是一把猪饲料,绿了芭蕉,肥了那杨柳小蛮腰,可怜我 ...

  8. 3.Linux 文件的压缩与打包

    1.常用压缩打包命令 常用的压缩打包扩展名为如下: *.Z compress 程序压缩的文件,非常老旧了,不再细说 *.gz gzip 程序压缩的文件: *.bz2 bzip2 程序压缩的文件: *. ...

  9. jmeter如何连接数据库

    大家都知道jmeter是java编写的,java/jmeter如果想连接数据库就要通过java database connector(JDBC)去连接,首先需先下载一个驱动 (mysql-connec ...

  10. extjs/js时间校验

    //时间秒判断var re=/^(?:19|20)[0-9][0-9]-(?:(?:0[1-9])|(?:1[0-2]))-(?:(?:[0-2][1-9])|(?:[1-3][0-1])) (?:( ...