字符串hash LA 4513 Stammering Aliens

题目传送门

题意:训练之南P225

分析:二分寻找长度,用hash值来比较长度为L的字串是否相等。

#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long ull;
const int N = 4e4 + 5;
const int x = 123;
ull H[N], _hash[N], xp[N];
int rk[N];
char str[N];
int m;

void get_hash(char *s, int len)  {
    H[len] = 0;
    for (int i=len-1; i>=0; --i) {
        H[i] = H[i+1] * x + (s[i] - ‘a‘);
    }
    xp[0] = 1;
    for (int i=1; i<len; ++i) {
        xp[i] = xp[i-1] * x;
    }
}

bool cmp(const int &a, const int &b) {
    return (_hash[a] < _hash[b] || (_hash[a] == _hash[b] && a < b));
}

int check(int L, int len)    {
    int cnt = 0, pos = -1, c = 0;
    for (int i=0; i<len-L+1; ++i)   {
        rk[i] = i;
        _hash[i] = H[i] - H[i+L] * xp[L];
    }
    sort (rk, rk+len-L+1, cmp);
    for (int i=0; i<len-L+1; ++i)   {
        if (i == 0 || _hash[rk[i]] != _hash[rk[i-1]])   c = 0;
        if (++c >= m)   pos = max (pos, rk[i]);
    }
    return pos;
}

int main(void)  {
    while (scanf ("%d", &m) == 1)   {
        if (!m) break;
        scanf ("%s", &str);
        int len = strlen (str);
        get_hash (str, len);
        if (check (1, len) == -1) puts ("none");
        else    {
            int l = 1, r = len + 1;
            while (r - l > 1)   {
                int mid = l + r >> 1;
                if (check (mid, len) >= 0)    l = mid;
                else    r = mid;
            }
            printf ("%d %d\n", l, check (l, len));
        }
    }

    return 0;
}

  

时间: 2024-10-11 12:51:22

字符串hash LA 4513 Stammering Aliens的相关文章

LA 4513 Stammering Aliens 字符串hash

字符串hash模板, 本题是求,给定字符串s中至少出现m次的最长字符串长度,及此时起始位置的最大值 LA 4513  Stammering Aliens 白书p225 //#pragma warning (disable: 4786) //#pragma comment (linker, "/STACK:16777216") //HEAD #include <cstdio> #include <ctime> #include <cstdlib> #i

UVALive - 4513 Stammering Aliens ——(hash+二分 || 后缀数组加二分)

题意:找一个出现了m次的最长子串,以及这时的最右的位置. hash的话代码还是比较好写的,,但是时间比SA多很多.. 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 using namespace std; 5 const int N = 40000 + 100; 6 typedef long long ll; 7 const int X = 257; 8 const int mod

uvalive 4513 Stammering Aliens

题意:给你一个串,问期中至少出现m次的最长子串及其起始位置的坐标. 思路:hash+LCP+二分答案 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn = 40000 + 10; 7 const int x = 123; 8 int n, m, pos; 9 unsigned long long H[maxn], x

poj 3882(Stammering Aliens) 后缀数组 或者 hash

后缀数组:  构建后缀数组,注意要在字符串莫末尾加上一个没出现过的字符.然后可以2分或者直接扫描,直接扫描需要用单调队列来维护 VIEW CODE #include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstrin

UVa 12206 (字符串哈希) Stammering Aliens

体验了一把字符串Hash的做法,感觉Hash这种人品算法好神奇. 也许这道题的正解是后缀数组,但Hash做法的优势就是编码复杂度大大降低. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 40000 + 10; 7 const int x = 123; 8 int n, m, pos; 9 unsigne

uva 12206 - Stammering Aliens(哈希)

题目链接:uva 12206 - Stammering Aliens 题目大意:给出一个字符串,找出至少出现m次的最长子串. 解题思路:哈希算法,将每个后缀数组建立一个哈希值,每次二分长度判断,每次判断时将哈希值排序,计数即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef unsigned long long ll; const int ma

UVA 12206 - Stammering Aliens(后缀数组)

UVA 12206 - Stammering Aliens 题目链接 题意:给定一个序列,求出出现次数大于m,长度最长的子串的最大下标 思路:后缀数组,搞出height数组后,利用二分去查找即可 这题之前还写过hash的写法也能过,不过写后缀数组的时候,犯了一个傻逼错误,把none输出成node还一直找不到...这是刷题来第二次碰到这种逗比错误了,还是得注意.. 代码: #include <cstdio> #include <cstring> #include <algori

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

POJ 3882 Stammering Aliens 后缀数组height应用

题目来源:POJ 3882 Stammering Aliens 题意:给你m一个一个字符串 求至少出现m次的最长字符串 可以在字符串中重叠出现 思路:二分长度l 然后从height数组中找长度大于等于l的前缀 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 40010; char s[maxn]; int sa[maxn]; i