CodeForces - 727E Games on a CD 字符串Hash
题意:有n个单词,每个单词长度为k,顺时针将它们写成一个圆圈串。现在知道g个长度为k的单词,是否可以从这g个单词中选择n个形成这个圆圈串?如果有多个答案,任意输出一个。
思路
可以发现,如果枚举第一个串的开始位置,由于输入的g个串,长度都为k,那么每个串的位置就固定了。那么我只要知道,在主串上那一段位置的字符串,是否存在在g个串中,然后如果每个都存在,那么就是符合的。这一部分可以用字符串hash做到O(1)判断。
复杂度的话,枚举第一个串的复杂度是k,一共需要匹配n个字符串,所以总复杂度是O(nk)
要注意不能用自然溢出写,因为可以造出数据卡掉自然溢出,这里我是用双哈希写的。
字符串Hash
hash[i] = (hash[i-1]*p + idx(i)) % mod;
字符串子串Hash
hash[l,r] = (hash[r] - hash[l-1]*p^(r-l+1) + mod) % mod;
在这里,p和mod是两个质数。
AC代码
#include <cstdio>
#include <cmath>
#include <cctype>
#include <bitset>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define pii pair<int, int>
typedef long long LL;
const double Pi = acos(-1.0);
const int maxn = 2e6 + 5;
const int seed = 1007;
const int mod[2] = {1000000007, 1000000009};
char s[maxn];
int Hash[2][maxn], ans[maxn];
int f[2][maxn], vis[maxn], tim;
map<pii, int>arr;
// hash[i] = (hash[i-1]*p + idx(i)) % mod;
// hash[l,r] = (hash[r] - hash[l-1]*p^(r-l+1)) % mod;
void init() {
for(int i = 0; i < 2; ++i) {
f[i][0] = 1;
for(int j = 1; j < maxn; ++j) {
f[i][j] = (LL)f[i][j-1] * seed % mod[i];
}
}
}
pii getHash(char *s) {
int res[2] = {0, 0};
int n = strlen(s);
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < n; ++j) {
res[i] = ((LL)res[i] * seed + s[j]) % mod[i];
}
}
return pii(res[0], res[1]);
}
pii getHash(int l, int r) {
int res[2];
for(int i = 0; i < 2; ++i) {
res[i] = (Hash[i][r] - (LL)Hash[i][l-1] * f[i][r-l+1] % mod[i] + mod[i]) % mod[i];
}
return pii(res[0], res[1]);
}
void getPre(char *s, int k) {
int n = strlen(s+1);
for(int i = 0; i < 2; ++i) {
Hash[i][0] = 0;
for(int j = 1; j <= n; ++j) {
Hash[i][j] = ((LL)Hash[i][j-1] * seed + s[j]) % mod[i];
}
for(int j = n+1, t = 1; t < k ; ++t, ++j)
Hash[i][j] = ((LL)Hash[i][j-1] * seed + s[t]) % mod[i];
}
}
bool check(int st, int n, int k) {
tim++;
int l = st, r = st + k - 1;
for(int i = 1; i <= n; i++, l += k, r += k) {
pii p = getHash(l, r);
if(!arr.count(p)) return 0;
int val = arr[p];
if(vis[val] == tim) return 0; //判重
vis[val] = tim;
ans[i] = val;
}
printf("YES\n");
for(int i = 1; i <= n; ++i) {
printf("%d%c", ans[i], i == n ? '\n' : ' ');
}
return 1;
}
int main() {
init();
int n, k;
while(scanf("%d%d", &n, &k) == 2) {
tim = 1;
arr.clear();
scanf("%s", s+1);
getPre(s, k);
int g;
scanf("%d", &g);
for(int i = 1; i <= g; ++i) {
scanf("%s", s);
pii p = getHash(s);
arr[p] = i;
}
bool ok = 0;
for(int i = 1; i <= k; ++i) {
if(check(i, n, k)) {
ok = 1;
break;
}
}
if(!ok) printf("NO\n");
}
return 0;
}
如有不当之处欢迎指出!
CodeForces - 727E Games on a CD 字符串Hash的更多相关文章
- 【codeforces 514C】Watto and Mechanism(字符串hash)
[题目链接]:http://codeforces.com/contest/514/problem/C [题意] 给你n个字符串; 然后给你m个询问;->m个字符串 对于每一个询问字符串 你需要在 ...
- 【题解】 Codeforces Edu44 F.Isomorphic Strings (字符串Hash)
题面戳我 Solution 我们按照每个字母出现的位置进行\(hash\),比如我们记录\(a\)的位置:我们就可以把位置表示为\(0101000111\)这种形式,然后进行字符串\(hash\) 每 ...
- Codeforces 898F - Restoring the Expression(字符串hash)
898F - Restoring the Expression 思路:字符串hash,base是10,事实证明对2e64取模会T(也许ull很费时),对1e9+7取模. 代码: #include< ...
- 【CodeForces727E/CF727E】Games on a CD (字符串哈希)
题目: CodeForces727E 分析: 看到字符串比较,肯定想到哈希啊--现学的哈希,先丢两个重要的公式 (\(seed\)是大于字符集大小的质数,\(p\)是大质数) \[hash[i]=(h ...
- CodeForces 1056E - Check Transcription - [字符串hash]
题目链接:https://codeforces.com/problemset/problem/1056/E One of Arkady's friends works at a huge radio ...
- codeforces gym 101164 K Cutting 字符串hash
题意:给你两个字符串a,b,不区分大小写,将b分成三段,重新拼接,问是否能得到A: 思路:暴力枚举两个断点,然后check的时候需要字符串hash,O(1)复杂度N*N: 题目链接:传送门 #prag ...
- 线段树 + 字符串Hash - Codeforces 580E Kefa and Watch
Kefa and Watch Problem's Link Mean: 给你一个长度为n的字符串s,有两种操作: 1 L R C : 把s[l,r]全部变为c; 2 L R d : 询问s[l,r]是 ...
- 洛谷P3234 抄卡组 [HNOI2014] 字符串hash
正解:字符串hash 解题报告: 传送门! 字符串hash是字符串匹配中很常见的一个方法,原理也很好懂,这里就不做太多阐述辣有时间放到hash笔记里面去QAQ 题意不说了挺好理解的,自带一句话概括好评 ...
- [知识点]字符串Hash
1.前言 字符串的几大主要算法都多少提及过,现在来讲讲一个称不上什么算法, 但是非常常用的东西——字符串Hash. 2.Hash的概念 Hash更详细的概念不多说了,它的作用在于能够对复杂的状态进行简 ...
随机推荐
- Python---socket库
为方便以后查询和学习,特从常用库函数和示例来总结socket库 1. 术语 family:AF_INET socktype:SOCK_STREAM或SOCK_DGRAM protocol:IPPROT ...
- Linux指令--grep
原文地址:http://www.cnblogs.com/peida/archive/2012/12/17/2821195.html.感谢作者的无私分享. Linux系统中grep命令是一种强大的文本搜 ...
- POI--HSSFCellStyle类
通过POI来进行单元格格式的设定 设定格式使用「HSSFCellStyle」类.它有一个构造方法: protected HSSFCellStyle(short index, ExtendedForma ...
- @@IDENTITY详细测试
今天看数据库SQL,有发现存储过程中有使用到SCOPE_IDENTITY()这个函数,后来问了下谷歌大婶,搜到一个比较重要的博客,链接如下:https://dotblogs.com.tw/kkman0 ...
- Matlab实用技巧
1 Matlab Cell 编程模式 在一个长长的脚本m文件中,可能需要对其中的一段反复修改,查看执行效果,这时,cell模式就非常有用了.cell模式相当于将其中的代码拷贝到命令窗口中运行.两个% ...
- ehcache模糊批量移除缓存
目录 前言 实现 总结 前言 众所周知,encache是现在最流行的java开源缓存框架,配置简单,结构清晰,功能强大.通过注解@Cacheable可以快速添加方法结果到缓存.通过@CacheEvic ...
- [PHP]接口请求校验的原理
具体的校验步骤可以自定义,下面是比较直观的一种形式: 1. 客户端:请求参数带上时间,进行首字母排序,连接私钥后,取得加密结果: 客户端请求时带上这个加密结果作为sign参数. 2. 服务端:对sig ...
- WTF小程序之wxs
前言 对于从VUE过来的前端同学来说,见到小程序的第一眼一定是熟悉-感觉就像是把vue的单文件拆成了3个文件.但是,随着慢慢入坑.马上会发现,这样怎么不行?wxs文件又是什么鬼?template和vu ...
- FreeMarker template error: The following has evaluated to null or missing: ==> blogger.md [in template "admin/about.ftl" at line 44, column 84]
FreeMarker template error:The following has evaluated to null or missing:==> blogger.md [in templ ...
- 【Tomcat】Tomcat的使用
第一章 JDK的安装 1.1 windows下安装 1.1.1 配置环境变量 安装完成后,还要进行 Java 环境的配置,才能正常使用,步骤如下: (1)在我的电脑点击右键——〉选择属性, (2) ...