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更详细的概念不多说了,它的作用在于能够对复杂的状态进行简 ...
随机推荐
- linkin大话设计模式--适配器模式
linkin大话设计模式--适配器模式 大家知道,在java中只允许单继承,但是在实际问题中往往都需要多继承,java引入了接口这一概念.(一个类可以实现多个接口) 由于接口中都是抽象方法,那么我们在 ...
- remoteViews简介
RemoteViews从字面上看是一种远程视图.RemoteViews具有View的结构,既然是远程View,那么它就可以在其他进程中显示.由于它可以跨进程显示,所以为了能够更新他的界面,Remote ...
- CU社区shell板块awk十三问整理
CU社区shell板块awk十三问整理 一.RS="" 当 RS="" 时,会将\n强制加入到FS变量中,因为RS为空时,是将连续多空行作为分隔符,近似于\n\ ...
- 【转】十分有用的linux shell学习总结
在最近的日常工作中由于经常会和Linux服务器打交道,如Oracle性能优化.我们 数据采集服务器的资源利用率监控,以及Debug服务器代码并解决其效率和稳定性等问题.因此这段时间总结的有关Linux ...
- 【转】用Linux命令行获取本机外网IP地址
$ curl ifconfig.me $ curl icanhazip.com $ curl ident.me $ curl ipecho.net/plain $ curl whatismyip.ak ...
- CSS——选择器2
1.子选择器 (1).用于指定标签元素的第一代子元素,使用">"号. (2).例子: <style type="text/css"> .foo ...
- Asp.net Core 入门实战 2.请求流程
Asp.Net Core 是开源,跨平台,模块化,快速而简单的Web框架. Asp.net Core官网的一个源码合集,方便一次性Clone,喜欢的(Star),本系列持续更新,也可以通过我的网站访问 ...
- redis 简易监控的几种方法
简介 针对Redis 实现性能监控的几种方法 一.使用info命令 命令说明 127.0.0.1:6380> info # Server redis_version:3.2.11 redis_g ...
- 02_Python基本数据类型
一.什么是数据 数据是描述客观事物的字符(比如95,不同的语义可表示成绩或体重),是计算机可以操作的对象,能够被计算机识别并输入给计算机处理的符号集合. 数据不仅仅包含整形,还包括图像.音乐.视频等非 ...
- jira + confluence 安装和破解
Window环境: 环境准备 安装JAVA1.8以上版本 安装SQL SERVER 或 MySQL: jira安装和破解 下载安装包 https://downloads.atlassian.com/s ...