字符串\(Hash\).

笔者实在太菜了,到现在还没有熟练掌握\(Hash\),就来这里写一篇学习笔记。

\(Description\)

有三个好朋友喜欢在一起玩游戏,\(A\)君写下一个字符串\(S,B\)君将其复制一遍得到\(T,C\)君在T的任意位置(包括首尾)插入一个字符得到\(U\).现在你得到了\(U\),请你找出\(S.\)

\(Input\)

第一行一个数\(N\),表示\(U\)的长度.

第二行一个字符串\(U\),保证\(U\)由大写字母组成

\(Output\)

输出一行,若S不存在,输出"NOT POSSIBLE".若\(S\)不唯一,输出"NOT UNIQUE".否则输出\(S.\)

字符串\(Hash\),可以快速做到字符串匹配。比如,从一个字符串中选择两个子串进行匹配,还是要\(Hash\)的。

\(Hash\)是一种随机算法。我们设计一个\(Hash\)函数:

设字符串\(C=c_1c_2...c_n\),\(K\)为字符串的长度(前\(K\)个)

选择两个数\(b,h\),满足\(b<h,b\)与\(h\)互质。

我们有:

\(Hash(C,K)=Hash(C,K-1)*b+c_k\)

所以,我们的复杂度瓶颈就在处理\(b\)上了。

对上面的函数拆开来写,就是:

设\(x=m-1\),

\(Hash(C)=(c_1*b^x+...+c_m*1) mod h\)

预处理\(b\)的次幂,递推即可。

考虑一下\(Hash\)冲突的问题。

我们前面取了一个模数\(h=Mod\)对吧。后面我写成\(Mod\).

显然,对于任意串的\(Hash\)值一定是模\(Mod\)意义下剩余系中的一个,可以认为在区间\([0,Mod-1]\)中随机分布。

考虑几个串不相等。

对于第一个串,有\(\frac{Mod-1}{Mod}\)的概率。

如果第二个要和第一个不相等,就只有\(\frac{Mod-2}{Mod}\)的概率。

以此类推,所有串不相等的概率为:

\(\frac{Mod-1}{Mod}*\frac{Mod-2}{Mod}*...*\frac{Mod-i+1}{Mod}\)

\(i\)是子串数(枚举)。

当我们把模数\(1e9\),字符串数达到\(1e5\)的时候,不冲突的概率为:

\(0.006737160911819992\)

在这么大的数据下,显然冲突的概率非常高。如何提高它不冲突的概率?

我们选择模数的时候,发现模数越大,冲突概率越小。那我们就可以利用\(unsigned long long\),自然溢出即可。

还可以双\(Hash\),然而笔者太菜,不会,就先不说了,其实就是在就算一遍\(Hash\)后再计算几遍,只有\(Hash\)值全部相等才算匹配成功。

考虑单\(Hash\)。

这道题,我们的思路就是,枚举断点,然后计算前后两个子串的\(Hash\)是否匹配。

取一段子串的\(Hash\)值时,记住:

当其起点为\(i\),终点为\(j\)时(子串),

\(Hash=H[r]-H[l-1]*power[r-l+1]\)

其中\(H\)数组是计算主串\(Hash\)时计算出来的。

这道题注意一下细节即可。判重的时候,如果与前面有一样的答案,算一个。除非是答案中的字符串不同,才算多重答案。

\(Code:\)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
typedef unsigned long long ull;
const int B=2333333;
const int H=1e9+9;
int n,vis,L;
ull power[2000010],h[2000010],last;
char s[2000010],a[2000010];
ull Get(int l,int r){return h[r]-h[l-1]*power[r-l+1];}
bool check(int pos){
ull x,y,z;
int flag=0;
if(pos<L){
x=Get(1,pos-1)*power[L-pos]+Get(pos+1,L);
y=Get(L+1,n);
}
else if(pos>L){
x=Get(1,L-1);
y=Get(L,pos-1)*power[n-pos]+Get(pos+1,n);
}
else if(pos==L){
x=Get(1,L-1);
y=Get(L+1,n);
}
if(x==y){
if(x==last)return 0;
last=x;
int top=0;
if(pos<=L)
for(int i=L+1;i<=n;++i)
a[++top]=s[i];
else
for(int i=1;i<=L-1;++i)
a[++top]=s[i];
return true;
}
return 0;
}
int main(){
scanf("%d",&n);
scanf("%s",s+1);
power[0]=1;
if(n%2==0){
printf("NOT POSSIBLE\n");
return 0;
}
for(int i=1;i<=n;++i)
power[i]=power[i-1]*B;
for(int i=1;i<=n;++i)
h[i]=h[i-1]*B+s[i];
L=(n>>1)+1;
for(int i=1;i<=n;++i){
vis+=check(i);
if(vis>1)break;
}
if(!vis){
printf("NOT POSSIBLE\n");
return 0;
}
else if(vis>1){
printf("NOT UNIQUE\n");
return 0;
}
else puts(a+1);
return 0;
}

【题解】Bzoj3916的更多相关文章

  1. 【题解】 bzoj3916: [Baltic2014]friends (字符串Hash)

    题面戳我 Solution 首先长度为偶数可以直接判掉 然后我们可以枚举删的位置,通过预处理的\(hash\),判断剩余部分是否划分成两个一样的 判重要注意,我们把字符串分为三个部分\(L_l+1+L ...

  2. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  3. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  4. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  5. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  6. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  7. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  8. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  9. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

随机推荐

  1. sdf文件可以通过database net4工具升级版本

    用database .net4工具打开数据库后,右键数据库->数据库工具->upgrade to->to 4.0 or to 3.5; 可以用来判断数据库版本及是否要升级.

  2. [HGAME] Week1 Web WriteUp

    一 .Cosmos的博客 打开题目之后,首页直接给了我们提示: 版本管理工具常用的有git和svn两种,这里提示了GitHub,考虑Git信息泄露,先访问/.git/目录考虑用Githack获取泄露信 ...

  3. 终于开始了,微软的野心将通过全场景开发平台dotnet 5体现得淋漓尽致!

      本文已经同步到微信公众号「极客起源」 . 现在都在谈论全场景开发,也就是用一套开发工具,可以开发包括但不限于桌面.移动.IOT.游戏.Web等平台的应用.这样对于开发人员是非常爽的.本文将介绍微软 ...

  4. 消息队列之-RocketMQ入门

    简介 RocketMQ是阿里开源的消息中间件,目前已经捐献个Apache基金会,它是由Java语言开发的,具备高吞吐量.高可用性.适合大规模分布式系统应用等特点,经历过双11的洗礼,实力不容小觑. 官 ...

  5. Java里一个线程两次调用start()方法会出现什么情况

    Java的线程是不允许启动两次的,第二次调用必然会抛出IllegalThreadStateException,这是一种运行时异常,多次调用start被认为是编程错误. 如果业务需要线程run中的代码再 ...

  6. asp.net中 使用Nginx 配置 IIS站点负载均衡

    这是一偏初学者入门的内容,发现有问题的地方,欢迎留言,一起学习,一起进步 本文主要记录一下在Windows平台中,IIS站点如何使用Nginx 做一个简单的负载均衡  一. 准备工作: 官网下载安装包 ...

  7. xargs命令学习,于阮一峰博客

    一.标准输入与管道命令 Unix 命令都带有参数,有些命令可以接受"标准输入"(stdin)作为参数. $ cat /etc/passwd | grep root 上面的代码使用了 ...

  8. SpringMVC-09-Ajax技术

    9. Ajax技术 简介 AJAX=Asynchronous JavaScript and XML (异步的JavaScript和XML) AJAX是一种在无需重新加载整个网页的情况下,能够更新部分网 ...

  9. bernoulli, multinoulli distributions 讲解

    bernoulli, multinoulli distributions 讲解   常用概率分布-Bernoulli 分布 & Multinoulli 分布 转自:迭代自己-19常用概率分布 ...

  10. PHP程序十点未来的建议

    1. Composer 第一点就要提 Composer ,自从 Composer 出现后,PHP 的依赖管理可以变得非常简单.程序内依赖一些类库和框架,直接使用 Composer 引入即可,通过使用 ...