Wannafly挑战赛11 D 白兔的字符串 Hash

Wannafly挑战赛11

D   白兔的字符串

白兔有一个字符串T。白云有若干个字符串S1,S2..Sn

白兔想知道,对于白云的每一个字符串,它有多少个子串是和T循环同构的。

提示:对于一个字符串a,每次把a的第一个字符移动到最后一个,如果操作若干次后能够得到字符串b,则a和b循环同构。

所有字符都是小写英文字母

输入描述:

第一行一个字符串T(|T|<=10^6)第二行一个正整数n (n<=1000)接下来n行为S1~Sn (|S1|+|S2|+…+|Sn|<=10^7),max(|S1|,|S2|,|S3|,|S4|,..|Sn|)<=10^6

输出描述:

输出n行表示每个串的答案

示例1

输入

abab
2
abababab
ababcbaba

输出

5
2

tags:字符串 Hash

把 T 在 Hash 后存在 set 里,再对每个 S 找子串。但要用 unordered_set ,否则会超时。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
typedef  unsigned long long  ull;
const int N = 1000005, Base=1e9+7;

unordered_set< ull > Set;
ull  p[N];
void Init(char* T)
{
    int len = strlen(T);
    ull  Hash = 0;
    p[0] = 1;
    rep(i,0,len-1) {
        Hash = Hash*Base+T[i];
        p[i+1] = p[i]*Base;
    }
    rep(i,0,len-1) {
        Hash = (Hash-T[i]*p[len-1])*Base + T[i];
        Set.insert(Hash);
    }
}
int solve(char* S, int lenT)
{
    int lenS = strlen(S);
    if(lenS < lenT) return 0;
    ull  Hash = 0;
    int ret = 0;
    rep(i,0,lenT-1) Hash = Hash*Base+S[i];
    if(Set.count(Hash)) ++ret;
    rep(i,lenT,lenS-1) {
        Hash = (Hash-S[i-lenT]*p[lenT-1])*Base + S[i];
        if(Set.count(Hash)) ++ret;
    }
    return ret;
}
char T[N], S[N];
int main()
{
    scanf("%s", T);
    Init(T);
    int lenT = strlen(T);
    int n;  scanf("%d", &n);
    while(n--)
    {
        scanf("%s", S);
        printf("%d\n", solve(S, lenT));
    }

    return 0;
}

正解是:

标算是ex_kmp。用R[i]表示S[i..len]和T的最长公共前缀,L[i]表示S[1..i]和T的最长公共后缀,当L[i]+R[i+1]>=|T|时,可以给一段区间打上标记。如果T的一个表示法在某个位置出现则至少会被一个标记覆盖。然后就变成了区间加法,求有多少个正数。用差分+前缀和即可。

原文地址:https://www.cnblogs.com/sbfhy/p/8552524.html

时间: 2024-10-16 14:15:49

Wannafly挑战赛11 D 白兔的字符串 Hash的相关文章

hdu 1880 魔咒词典(字符串hash)

题目链接:hdu 1880 魔咒词典 题意: 给你一个10w的词典,让你输出对应的字段. 题解: map暴力存字符串肯定会卡内存,这里用BKDR字符串hash一下,用map映射一下. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 typedef unsigned long long ull; 5 6 const int N=1e5+7,seed=133

【二分答案+智障的字符串hash】BZOJ2946-[Poi2000]公共串(Ranklist倒一达成!!!!!)【含hash知识点】

[题目大意] 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. [字符串hash的小笔记] hash[i]=(hash[i-1]*p+idx(s[i]))%mod,idx为映射值,一般a..z映射1..26: 习惯上,p取一个6到8位的素数即可,mod一般取大素数 1e9+7(1000000007)或1e9+9(1000000009). hash[i]=(hash[i-1]*p+idx(s[i]))%mod 表示第 i 个前缀的hash值,是一个hash的前缀和,那么,要求S[l…r]

uva 10391 Compound Words (字符串-hash)

Problem E: Compound Words You are to find all the two-word compound words in a dictionary. A two-word compound word is a word in the dictionary that is theconcatenation of exactly two other words in the dictionary. Input Standard input consists of a

HDU 4821 字符串hash

题目大意: 希望找到连续的长为m*l的子串,使得m个l长的子串每一个都不一样,问能找到多少个这样的子串 简单的字符串hash,提前预处理出每一个长度为l的字符串的hash值 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <map> 6 #include <set> 7 8 using na

【转】各种字符串Hash函数比较

常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎不可能找到碰撞. 常用字符串哈希函数有BKDRHash,APHash,DJBHash,JSHash,RSHash,SDBMHash,PJWHash,ELFHash等等.对于以上几种哈希函数,我对其进行了一个小小的评测. Hash函数 数据1 数据2 数据3 数据4 数据1得分 数据2得分 数据3得分

记录几个经典的字符串hash算法

记录几个经典的字符串hash算法,方便以后查看: 推荐一篇文章: http://www.partow.net/programming/hashfunctions/# (1)暴雪字符串hash 1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <stdint.h> 5 #include <stdbool.h> 6 7 #define MAXTABL

常用字符串Hash函数

几个常用的字符串Hash函数如下: SDBMHash函数 unsigned int SDBMHash(char *str) { unsigned int hash = 0; while (*str) { // equivalent to: hash = 65599*hash + (*str++); hash = (*str++) + (hash << 6) + (hash << 16) - hash; } return (hash & 0x7FFFFFFF); } RSHa

转载:字符串hash总结(hash是一门优雅的暴力!)

转载自:远航休息栈 字符串Hash总结 Hash是什么意思呢?某度翻译告诉我们: hash 英[hæ?] 美[hæ?]n. 剁碎的食物; #号; 蔬菜肉丁;vt. 把…弄乱; 切碎; 反复推敲; 搞糟; 我觉得Hash是引申出 把...弄乱 的意思. 今天就来谈谈Hash的一种——字符串hash. 据我的理解,Hash就是一个像函数一样的东西,你放进去一个值,它给你输出来一个值.输出的值就是Hash值.一般Hash值会比原来的值更好储存(更小)或比较. 那字符串Hash就非常好理解了.就是把字符

Wannafly挑战赛22游记

Wannafly挑战赛22游记 幸福的人都是相似的,不幸的人各有各的不幸. --题记 A-计数器 题目大意: 有一个计数器,计数器的初始值为\(0\),每次操作你可以把计数器的值加上\(a_1,a_2,\ldots,a_n\)中的任意一个整数,操作次数不限(可以为\(0\)次),问计数器的值对\(m\)取模后有几种可能. 思路: 由裴蜀定理易得,答案即为\(\frac m{\gcd(m,a_1,a_2,\ldots,a_n)}\). 源代码: #include<cstdio> #include