SPOJ DISUBSTR(字符串hash)

传送门:DISUBSTR

题意:给定一个字符串,求不同子串个数。

分析:由于数据较小,直接枚举长度为1,2...n的所有子串进行hash即可,复杂度(O(n^2)),后缀数组才是正解(O(nlogn)。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <map>
#define LL long long
#define N 1000010
using namespace std;
const int HASH=10007;
const int MAXN=1010;
struct HASHMAP
{
    int head[HASH],next[MAXN],size;
    unsigned long long state[MAXN];
    int f[MAXN];
    void init()
    {
        size=0;
        memset(head,-1,sizeof(head));
    }
    int insert(unsigned long long val)
    {
        int h=val%HASH;
        for(int i=head[h];~i;i=next[i])
        {
            if(val==state[i])
            {
                return 0;
            }
        }
        state[size]=val;
        next[size]=head[h];
        head[h]=size++;
        return 1;
    }
}H;
const int SEED=13331;
unsigned long long p[MAXN];
unsigned long long s[MAXN];
char str[MAXN];
int main()
{
    p[0]=1;
    for(int i=1;i<MAXN;i++)p[i]=p[i-1]*SEED;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",str);
        int n=strlen(str);
        s[0]=0;
        for(int i=1;i<=n;i++)
        {
            s[i]=s[i-1]*SEED+str[i-1];
        }
        int ans=0;
        for(int L=1;L<=n;L++)
        {
            H.init();
            for(int i=1;i+L-1<=n;i++)
            {
                int res=H.insert(s[i+L-1]-s[i-1]*p[L]);
                ans+=res;
            }
        }
        printf("%d\n",ans);
    }
}

时间: 2024-08-05 09:13:09

SPOJ DISUBSTR(字符串hash)的相关文章

SPOJ - DISUBSTR Distinct Substrings (不相同的子串的个数)

Distinct Substrings  Time Limit: 159MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description Given a string, we need to find the total number of its distinct substrings. Input T- number of test cases. T<=20;Each test case consists of

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]

hdu4821 String 字符串hash(bkdrhash)

题意:给定m,l,一个字符串str. 我们定义一个子串为"recoverable"串 当 1.长度为 M*L 2.把这个好串分成M段,每段长度为L,且每段各不相同. 求"recoverable"串的个数,串相同位置不同也算不同. 思路:预处理数组hash,hash[i]表示从i位置到尾的字符串hash值.这里数组为unsigned long long型,因为可以自动取模.然后枚举 前l个位置,每次向后翻滚(将前一个长度为l的段hash值从map中去除,将翻滚后新出现

字符串hash + 二分答案 - 求最长公共子串 --- poj 2774

Long Long Message Problem's Link:http://poj.org/problem?id=2774 Mean: 求两个字符串的最长公共子串的长度. analyse: 前面在学习后缀数组的时候已经做过一遍了,但是现在主攻字符串hash,再用字符串hash写一遍. 这题的思路是这样的: 1)取较短的串的长度作为high,然后二分答案(每次判断长度为mid=(low+high)>>1是否存在,如果存在就增加下界:不存在就缩小上界): 2)主要是对答案的判断(judge函数

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

codeforces gym 101164 K Cutting 字符串hash

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

[知识点] 字符串Hash

1.前言 字符串的几大主要算法都多少提及过,现在来讲讲一个称不上什么算法, 但是非常常用的东西——字符串Hash. 2.Hash的概念 Hash更详细的概念不多说了,它的作用在于能够对复杂的状态进行简单的表达,更方便的用于判重.在搜索的时候,或是动规的时候,都有过类似的做法.在实际应用中,也是非常重要的,这也就是为什么存在什么暴雪公司的Hash算法等等:加密环节也是Hash的重要之处,MD5码就是一个经典的例子. 字符串Hash的方式多式多样,重点来解释一下最简单的,最常用的. 3.BKDRHa

线段树 + 字符串Hash - 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]是否是周期为d的重复串. analyse: n最大为1e5,且m+k最大也为1e5,这就要求操作1和操作2都要采用logn的算法,所以用线段树. 对于更新操作,使用区间更新就可解决. 主要是如何在logn的时间内完成询问操作. 我们采用线段树维护hash值的方法. 结合于类似KMP的性质,我们发现,字

bnu36907 Subpalindromes 字符串hash+线段树

bnu36907 Subpalindromes 字符串hash+线段树 题意:给一个字符串(<=1e5), 进行操作和查询(<=1e5). 1)将指定位置的字符改为c 2)询问l-r的子串,是否是回文串. 解法 :区间维护pl和pr,表示从左到右的hash和从右到左的hash,然后在up和query中合并区间,最后判断pl和pr是否相等即可. #include <cstdio> #include <ctime> #include <cstdlib> #inc