题目大意

  给你一个字符串 \(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. 【转】解决未能加载文件或程序集'WebGrease‘的问题

    在多个视图中,如果有使用共用的样式代码,可以把它们移至CSS文件中去.今天Insus.NET就举例一个例子来说明. 比如前2篇中<ASP.NET MVC图片管理(上传,预览与显示)>htt ...

  2. winform注册功能

    注册按钮事件: private void btnRegister_Click(object sender, EventArgs e) { string username = txtUserName.T ...

  3. vue学习记录②(hello world!)

    接着上篇vue-cli脚手架构建项目结构建好项目之后,就开始写个“hello world!”吧~~~ vue玩的都是组件,所以开发的也是组件. 1.新建helloworld.vue.(删除Hello. ...

  4. Git配置用户信息和SSH

    安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功! 1.配置用户信息 在命令行输入: $ git config --global ...

  5. JS:onmouseover 、onmouseout

    鼠标移动到P标签上时,改变文本和边框样式 <style type="text/css"> .onmouseover { color: red; border: 1px ...

  6. Odoo 开源微信小程序商城模块

    详见:http://oejia.net/blog/2018/09/13/oejia_weshop_about.html oejia_weshop Odoo 微信小程序商城模块 oejia_weshop ...

  7. 【English】十二、英语句子种类,陈述句、疑问句、祈使句、感叹句

    一.英语句子按照用途可以分为4类 种类.用途.例句 陈述句 用于说明事实或说话人的看法(事实不就是别人发起并被同意的看法) My name is Jennt Green. I like him bec ...

  8. vue watch监听验证码时,axios延迟发送post请求。

    标题写的全面一些,方便其他人检索,我就是找了半天找不到资料,最后自己搞定了. 原理: 每次监听到输入值变化,就打一个时间戳,然后暂停2秒再去提交post验证. 但是每次提交前,判断一下之前打的时间戳和 ...

  9. docker根据配置文件启动redis

    更多docker基本命令请自行查询. 1.首先拉取合适版本的docker镜像 docker pull redis:5 2.如果不需要更改什么配置或者仅仅测试用可以直接启动镜像运行容器,这里要说明的是根 ...

  10. Aspnet mvc移除WebFormViewEngine

    为了提高mvc的速度,在Global.asax中移除WebFormViewEngine protected void Application_Start() { RemoveWebFormEngine ...