题意:有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的更多相关文章

  1. 【codeforces 514C】Watto and Mechanism(字符串hash)

    [题目链接]:http://codeforces.com/contest/514/problem/C [题意] 给你n个字符串; 然后给你m个询问;->m个字符串 对于每一个询问字符串 你需要在 ...

  2. 【题解】 Codeforces Edu44 F.Isomorphic Strings (字符串Hash)

    题面戳我 Solution 我们按照每个字母出现的位置进行\(hash\),比如我们记录\(a\)的位置:我们就可以把位置表示为\(0101000111\)这种形式,然后进行字符串\(hash\) 每 ...

  3. Codeforces 898F - Restoring the Expression(字符串hash)

    898F - Restoring the Expression 思路:字符串hash,base是10,事实证明对2e64取模会T(也许ull很费时),对1e9+7取模. 代码: #include< ...

  4. 【CodeForces727E/CF727E】Games on a CD (字符串哈希)

    题目: CodeForces727E 分析: 看到字符串比较,肯定想到哈希啊--现学的哈希,先丢两个重要的公式 (\(seed\)是大于字符集大小的质数,\(p\)是大质数) \[hash[i]=(h ...

  5. CodeForces 1056E - Check Transcription - [字符串hash]

    题目链接:https://codeforces.com/problemset/problem/1056/E One of Arkady's friends works at a huge radio ...

  6. codeforces gym 101164 K Cutting 字符串hash

    题意:给你两个字符串a,b,不区分大小写,将b分成三段,重新拼接,问是否能得到A: 思路:暴力枚举两个断点,然后check的时候需要字符串hash,O(1)复杂度N*N: 题目链接:传送门 #prag ...

  7. 线段树 + 字符串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]是 ...

  8. 洛谷P3234 抄卡组 [HNOI2014] 字符串hash

    正解:字符串hash 解题报告: 传送门! 字符串hash是字符串匹配中很常见的一个方法,原理也很好懂,这里就不做太多阐述辣有时间放到hash笔记里面去QAQ 题意不说了挺好理解的,自带一句话概括好评 ...

  9. [知识点]字符串Hash

    1.前言 字符串的几大主要算法都多少提及过,现在来讲讲一个称不上什么算法, 但是非常常用的东西——字符串Hash. 2.Hash的概念 Hash更详细的概念不多说了,它的作用在于能够对复杂的状态进行简 ...

随机推荐

  1. 提示让IE8以下版本的浏览器去更新浏览器

    需求: 强制让IE进行页面渲染时候,用最新的方式渲染,并提示让IE8以下的版本去更新浏览器并给一个连接地址 那,如何满足? <!DOCTYPE html> <html lang=&q ...

  2. 防盗链[referer]

    原文出处:http://www.cnblogs.com/devilfree/archive/2012/09/11/2680914.html 总结一下今天学习防盗链Filter的一些知识点: 防盗链要实 ...

  3. org.apache.catalina.util.DefaultAnnotationProcessor cannot be cast to org.apache.AnnotationProcessor

    这几天来公司,公司的SVN坏掉了,然后项目还比较大,是一个分布式的,然后同事就把项目发我了.我在myeclipse里面导入项目了,把相应的jar包也建了个人的library导入了项目,现在项目不报错了 ...

  4. 设置PATH和CLASSPATH

    每天玩java的,如果连这门语言背景一点都熟悉的话,说出去真的是挺丢人的一件事情. 首先,java具有最强大的2个特点:功能强大,简单易用.出去android不说,这门语言衍生出太多的开源框架了,这也 ...

  5. jenkins构建一个maven项目[五]

    标签(linux): jenkins 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 构建一个maven项目,即为构建java项目.模拟实验之前先把实验代码推送到 ...

  6. 理解javascript模块化(转)

    模块化是一个通用的编程最佳实践.程序的模块化使我们可以更方便地使用别人的代码,想要什么功能,就加载什么模块,从而提高代码的利用效率,增加开发速度. 模块就像积木,有了它,我们可以搭出各种各种功能样式的 ...

  7. 使用localhost可以访问,但使用本地ip+端口号无法访问

    今天想使用ip访问本机的iview-admin项目,结果怎么配置都无法访问,根据iview工程执行的命令npm run dev了解到是webpack配置的问题,打开工程里的node_modules文件 ...

  8. Django中模板的用法简介

    1. 模板系统的介绍 Django作为一个Web框架,其模板所需的HTML输出静态部分以及动态内容插入 模板由HTML代码和逻辑控制代码构成 Django框架的模板语言的语法格式: {{var_nam ...

  9. Linux 下编译安装xDebug命令速记

    下载xdebug-2.2.4.tgz软件链接: http://pan.baidu.com/s/1jGHYRMA #解压 xdebugtar -zxvf xdebug-2.2.4.tgz #进入xdeb ...

  10. 洛谷 P3672 小清新签到题 [DP 排列]

    传送门 题意:给定自然数n.k.x,你要求出第k小的长度为n的逆序对对数为x的1~n的排列 $n \le 300, k \le 10^13$ 一下子想到hzc讲过的DP 从小到大插入,后插入不会对前插 ...