题目:

CodeForces727E

分析:

看到字符串比较,肯定想到哈希啊……现学的哈希,先丢两个重要的公式

(\(seed\)是大于字符集大小的质数,\(p\)是大质数)

\[hash[i]=(hash[i-1]*seed+s[i])mod \ p
\]

\[hash[l,r]=(hash[r]-hash[l-1]*seed^{r-l+1})mod \ p
\]

把哈希想象成\(seed\)进制数,第二个公式很容易推出来。注意写的时候要防止出现负数(详见代码)

为了降低取模后不同字符串获得相同哈希值 ("冲突") 的可能性,这里分别对两个不同的\(p\)取模,即“双哈希”。

既然原字符串是一个“环”,那么自然能想到将其复制一份接在原串末尾,然后枚举起始位置。由于模板串长\(k\)一定,且原串每一位都应该匹配,那么显然当起始位置一定则方案一定,且只需要枚举原串前\(k\)个位置作为起始位置即可讨论到所有情况。

对于每一个起始位置可以\(O(n)\)找出每一个位置的匹配方案,因此最终时间复杂度是\(O(nk)\)

代码:

不能不取模,也不能乱取模;不能偷懒直接把str倍长……否则就会像我一样在CF上惨遭卡常233

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <string>
using namespace std; namespace zyt
{
typedef long long ll;
typedef pair <ll, ll> pll;
const int N = 1e6 + 10, seed = 131, p[2] = {(int)1e9 + 7, (int)1e9 + 9};
ll F[N * 2][2], h[N * 2][2];
string str;
map <pll, int> id;
inline void init(const string &str)
{
F[0][0] = F[0][1] = 1;
for (int i = 1; i < str.size(); i++)
{
F[i][0] = F[i - 1][0] * seed % p[0];
F[i][1] = F[i - 1][1] * seed % p[1];
}
h[0][0] = h[0][1] = str[0] - 'a';
for (int t = 0; t < 2; t++)
for (int i = 1; i < str.size(); i++)
h[i][t] = (h[i - 1][t] * seed + str[i] - 'a') % p[t];
}
inline pll Hash(const string &s)
{
ll ans[2] = {0, 0};
for (int t = 0; t < 2; t++)
for (int i = 0; i < s.size(); i++)
ans[t] = (ans[t] * seed + s[i] - 'a') % p[t];
return make_pair(ans[0], ans[1]);
}
inline pll Hash(const int l, const int r)
{
int len = r - l + 1;
if (l == 0)
return make_pair(h[r][0], h[r][1]);
else
return make_pair(
(h[r][0] - h[l - 1][0] * F[len][0] % p[0] + p[0]) % p[0],
(h[r][1] - h[l - 1][1] * F[len][1] % p[1] + p[1]) % p[1]);
}
void work()
{
int n, k, g, len;
static char buf[N];
string str;
bool flag = false;
scanf("%d%d", &n, &k);
len = n * k;
scanf("%s", buf);
str = buf;
str += str.substr(0, k);
init(str);
scanf("%d", &g);
for (int i = 0; i < g; i++)
{
scanf("%s", buf);
str = buf;
id[Hash(str)] = i;
}
static int ans[N], vis[N];
memset(vis, -1, sizeof(vis));
for (int i = 0; i < k && !flag; i++)
{
pll p;
int cnt = 0;
for (int j = i; j < len + i && cnt < n; j += k)
if (id.count(p = Hash(j, j + k - 1)) && vis[id[p]] != i)
ans[cnt++] = id[p], vis[id[p]] = i;
else
break;
if (cnt == n)
flag = true;
}
if (flag)
{
printf("YES\n");
for (int i = 0; i < n; i++)
printf("%d ", ans[i] + 1);
}
else
printf("NO\n");
}
}
int main()
{
zyt::work();
return 0;
}

【CodeForces727E/CF727E】Games on a CD (字符串哈希)的更多相关文章

  1. CodeForces - 727E Games on a CD 字符串Hash

    题意:有n个单词,每个单词长度为k,顺时针将它们写成一个圆圈串.现在知道g个长度为k的单词,是否可以从这g个单词中选择n个形成这个圆圈串?如果有多个答案,任意输出一个. 思路 可以发现,如果枚举第一个 ...

  2. Games on a CD

    Games on a CD time limit per test 4 seconds memory limit per test 512 megabytes input standard input ...

  3. HDU 1880 魔咒词典(字符串哈希)

    题目链接 Problem Description 哈利波特在魔法学校的必修课之一就是学习魔咒.据说魔法世界有100000种不同的魔咒,哈利很难全部记住,但是为了对抗强敌,他必须在危急时刻能够调用任何一 ...

  4. 洛谷P3370 【模板】字符串哈希

    P3370 [模板]字符串哈希 143通过 483提交 题目提供者HansBug 标签 难度普及- 提交  讨论  题解 最新讨论 看不出来,这题哪里是哈希了- 题目描述 如题,给定N个字符串(第i个 ...

  5. HDU2594 Simpsons’ Hidden Talents 字符串哈希

    最近在学习字符串的知识,在字符串上我跟大一的时候是没什么区别的,所以恶补了很多基础的算法,今天补了一下字符串哈希,看的是大一新生的课件学的,以前觉得字符串哈希无非就是跟普通的哈希没什么区别,倒也没觉得 ...

  6. LA 6047 Perfect Matching 字符串哈希

    一开始我用的Trie+计数,但是不是计多了就是计少了,后来暴力暴过去的…… 看了别人的代码知道是字符串哈希,但是仍有几个地方不理解: 1.26^500溢出问题 2.没考虑哈希碰撞? 跪求指点! #in ...

  7. AC日记——【模板】字符串哈希 洛谷 3370

    题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转 ...

  8. 从Hash Killer I、II、III论字符串哈希

    首先,Hash Killer I.II.III是BZOJ上面三道很经典的字符串哈希破解题.当时关于II,本人还琢磨了好久,但一直不明白为啥别人AC的代码都才0.3kb左右,直到CYG神犇说可以直接随机 ...

  9. 【NOIP模拟】Grid(字符串哈希)

    题目背景 SOURCE:NOIP2016-RZZ-1 T3 题目描述 有一个 2×N 的矩阵,矩阵的每个位置上都是一个英文小写字符. 现在需要从某一个位置开始,每次可以移动到一个没有到过的相邻位置,即 ...

随机推荐

  1. 08.C语言:特殊函数

    C语言:特殊函数 1.递归函数: 与普通函数比较,执行过程不同,该函数内部调用它自己,它的执行必须要经过两个阶段:递推阶段,回归阶段: 当不满足回归条件,不再递推: #include <stdi ...

  2. Java基础学习总结(88)——线程创建与终止、互斥、通信、本地变量

    线程创建与终止 线程创建 Thread类与 Runnable 接口的关系 public interface Runnable {         public abstract void run(); ...

  3. java 生成20位唯一ID,生成不会重复的20位数字----https://blog.csdn.net/weixin_36751895/article/details/70331781

    java 生成20位唯一ID,生成不会重复的20位数字----https://blog.csdn.net/weixin_36751895/article/details/70331781

  4. noip模拟赛 圆桌游戏

    [问题描述] 有一种圆桌游戏是这样进行的:n个人围着圆桌坐成一圈,按顺时针顺序依次标号为1号至n号.对1<i<n的i来说,i号的左边是i+1号,右边是i-1号.1号的右边是n号,n号的左边 ...

  5. 【HDOJ3068】最长回文(manacher)

    题意:求一个由小写字母组成的字符串中的最长回文长度 cas<=120 n<=110000 思路:试manacher板子 ..]of char; p:..]of longint; ch:an ...

  6. Tyvj1139 向远方奔跑(APIO 2009 抢掠计划)

    描述     在唐山一中,吃饭是一件很令人头疼的事情,因为你不可能每次都站在队伍前面买饭,所以,你最需要做的一件事就是——跑饭.而跑饭的道路是无比艰难的,因为路是单向的(你要非说成是双向的我也没法,前 ...

  7. docker mysql 主从配置

    docker安装运行单实例的MySQL参考另一篇文档 http://www.cnblogs.com/manger/p/7611309.html 1.首先在/data/script下创建两个文件my-m ...

  8. Spring MVC使用@RestController生成JSON示例

    继上一章的生成JSON示例http://www.cnblogs.com/EasonJim/p/7500405.html,现在还有另一种选择,就是使用@RestController,下面将参照上一节例子 ...

  9. python的setdefault

    Python 字典 setdefault() 方法和get()方法类似, 如果键不已经存在于字典中,将会添加键并将值设为默认值. dict.setdefault(key, default=None)

  10. 【CV论文阅读】YOLO:Unified, Real-Time Object Detection

    YOLO的一大特点就是快,在处理上可以达到完全的实时.原因在于它整个检测方法非常的简洁,使用回归的方法,直接在原图上进行目标检测与定位. 多任务检测: 网络把目标检测与定位统一到一个深度网络中,而且可 ...