题目大意

  给你一个字符串 \(s\),让你找出最大的 \(k\),满足:能从 \(s\) 中选出 \(k\) 个不重叠的字符串 \(t_1,t_2,\ldots,t_k\),且 \(\forall i,\lvert t_i\rvert >\lvert t_{i+1}\rvert\),\(t_{i+1}\) 是 \(t_i\) 的子串,\(t_{i+1}\) 的出现位置在 \(t_i\) 后面。

  \(n\leq 500000\)

题解

  显然最优方案中 \(t_{i+1}\) 就是把 \(t_i\) 的第一个字符或最后一个字符删掉得到的。

  记 \(f_i\) 为从 \(i\) 开始的后缀,选一个前缀作为 \(t_1\) 所能得到的最大的 \(k\)。

  那么可以二分 \(f_i\),然后判断 \(s_{i\sim i+f_i-1}\) 删掉前缀/后缀之后得到的字符串在后面任意一次出现的位置的 \(f\) 值是否 \(\geq f_i-1\)。

  这样是 \(O(n\log^2 n)\) 的。

  可以发现 \(f_i\leq f_{i+1}+1\)。因为如果 \(f_i>f_{i+1}+1\),那么把 \(f_i\) 的第一个字符扣掉就会得到一个开头在 \(i+1\),长度为 \(f_i-1\) 的方案。这样就不需要二分了。

  时间复杂度: \(O(n\log n)\)

  还有一种做法:

  注意到答案 \(\leq O(\sqrt n)\),那么就可以枚举每个长度 \(\leq 1000\) 的字符串,然后用哈希判断。

  时间复杂度:\(O(n\sqrt n)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<functional>
#include<cmath>
#include<vector>
#include<unordered_set>
//using namespace std;
using std::min;
using std::max;
using std::swap;
using std::sort;
using std::reverse;
using std::random_shuffle;
using std::lower_bound;
using std::upper_bound;
using std::unique;
using std::vector;
using std::unordered_set;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef std::pair<int,int> pii;
typedef std::pair<ll,ll> pll;
void open(const char *s){
#ifndef ONLINE_JUDGE
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
void open2(const char *s){
#ifdef DEBUG
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
const int N=500010;
bool f[1010][N];
bool s[7000007];
char str[N];
int n;
int h[N];
int main()
{
open("f");
scanf("%d",&n);
scanf("%s",str+1);
int ans=1;
memset(f[1],1,sizeof f[1]);
for(int j=1;j<=n;j++)
h[j]=str[j]-'a'+1;
for(int i=2;i<=1000;i++)
{
memset(s,0,sizeof s);
for(int j=n-i+1;j>=1;j--)
{
if(j+i<=n&&f[i-1][j+i])
s[h[j+i]]=1;
if(s[h[j]]||s[h[j+1]])
{
ans=i;
f[i][j]=1;
}
}
for(int j=1;j<=n-i+1;j++)
h[j]=(h[j]*129+str[j+i-1]-'a'+1)%7000007;
}
printf("%d\n",ans);
return 0;
}

【CF1063F】String Journey 哈希的更多相关文章

  1. [CF1063F]String Journey

    题意:定义长度为$k$的journey为一个字符串序列$t_{1\cdots k}$,对$\forall i\gt1$满足$t_i$是$t_{i-1}$的严格子串,定义字符串$s$上的journey为 ...

  2. [CF1063F]String Journey[后缀数组+线段树]

    题意 在 \(S\) 中找出 \(t\) 个子串满足 \(t_{i+1}\) 是 \(t_{i}\) 的子串,要让 \(t\) 最大. \(|S| \leq 5\times 10^5\). 分析 定义 ...

  3. 解题:CF1063F String Journey

    题面 分析性质以进行DP 性质1:一定有一个最优解通过每次删除第一个或最后一个字符达到 这个脑补一下就能证明了 那么我们设$dp[i]$表示后缀$[i,n]$选出一个前缀所能达到的最大长度,从右往左D ...

  4. CF1063F. String Journey(后缀数组+线段树)

    题目链接 https://codeforces.com/contest/1063/problem/F 题解 虽然本题有时间复杂度较高但非常好写的做法...... 首先,若答案为 \(k\),则一定存在 ...

  5. CF1063F String Journey DP、SAM、线段树

    传送门 为了方便把串反过来,条件变为\(t_i\)是\(t_{i+1}\)的真子串,答案显然不变. 一件重要的事情是必定存在一种最优解,字符串序列\(\{t\}\)满足\(|t_i| = i\). 考 ...

  6. Java中String的哈希值计算

    下面都是从String类的源码中粘贴出来的 private int hash; // Default to 0 public int hashCode() { int h = hash; if (h ...

  7. Redis 命令,键(key),字符串(String),哈希(Hash),列表(List),集合(Set)(二)

      Redis 命令 Redis 命令用于在 redis 服务上执行操作. 要在 redis 服务上执行命令需要一个 redis 客户端.Redis 客户端在我们之前下载的的 redis 的安装包中. ...

  8. laravel-- 在laravel操作redis数据库的数据类型(string、哈希、无序集合、list链表、有序集合)

    安装redis和连接redis数据库 在controller头部引入 一.基本使用 public function RedisdDbOne() { // 清空Redis数据库 Redis::flush ...

  9. [HDU 4821] String (字符串哈希)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821 题目大意:给你M,L两个字母,问你给定字串里不含M个长度为L的两两相同的子串有多少个? 哈希+枚 ...

随机推荐

  1. vs2015安装编辑神器:resharper10.0

    在平时的开发工作中,作为一名程序员,难免会想办法找到适合自己的开发编辑器.这款插件来自JetBrains公司.接下来就来教大家如何对这款软件进行安装与破解. 1:首先下载与安装.如果没有找到适合的资源 ...

  2. Eclipse设置全局用户名

    -Duser.name=你的名字

  3. es6 字符串的扩展和数值的扩展

    es6字符串的扩展 1. es6新增的一些方法 1.1 includes 判断是否包括在内,返回一个 true or false 1.2 statsWith 判断是否以什么开头,返回一个 true o ...

  4. HTML之body标签中的相关标签补充

    一 列表标签 列表标签分为三种. 1.无序列表<ul>,无序列表中的每一项是<li> 英文单词解释如下: a.ul:unordered list,“无序列表”的意思. b.li ...

  5. 二、Snapman多人协作电子表格之——软件下载安装与配置

    Snapman多人协作电子表格是一个即时工作系统. 一.软件下载地址 Snapman下载的官网地址:http://www.snapman.xyz 在官网下载Snapman主程序安装: snapman_ ...

  6. JMeter写入文件

    之前我们推文讨论过如何使用jmeter读取文件, 比如csv, txt文件读取, 只要配置csv数据文件, 即可非常容易的从文件中读取想要的数据,  但是如果数据已经从API或者DB中获取, 想存放到 ...

  7. What is “Neural Network”

    Modern neuroscientists often discuss the brain as a type of computer. Neural networks aim to do the ...

  8. Jenkins 配置GitLab插件和Git插件

    本文演示如何在安装完Jenkins之后,配置GitLab插件和Git插件. 1 安装插件 浏览器登录Jenkins Web UI,点击系统管理,再点击管理插件,切换到可选插件,分别搜索GitLab P ...

  9. 安装Docker时错误提示 "could not change group /var/run/docker.sock to docker: group docker not found"的解决方案

    安装Dock服务,主要命令是  yum install docker. 但是在启动的时候报错:warning msg="could not change group /var/run/doc ...

  10. nginx地址代理(2)

    本章要讲的是服务器的代理: Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器, 一对一代理:就一个服务器监听 server { listen       ...