[HDU 4080] Stammering Aliens (字符串哈希+二分)

原创 2016年08月30日 20:14:27

链接

HDU 4080


题意

每组数据为一个整数m和一个长度不小于m的字符串,求该字符串的一个子串,该子串在满足出现次数不小于m的同时应尽量长。
输出该长度和最右侧出现的起始位置。如果存在多组数据,输出有最靠近右侧的那组。


思路

关于子串和长度的题目仿佛都可以用字符串哈希+二分来水一水。
这题仍然是字符串哈希的题目,对这个字符串求哈希,然后二分长度,枚举对应长度的子串哈希。每个哈希值要存储在哈希表里并记录次数,由于定长子串的哈希是从左向右线性枚举的,因此很容易找到最右侧的解。
我使用了双重哈希,存储哈希表的方式不太好,是沿着环顺序存储的而不是链式存储,这样发生冲突每次都要顺次去找位置,很耗时。自然溢出的单重哈希也是可以过的,只要存得好。


代码

#include <cstdio>
#include <iostream>
#include <cstring>
#include <set>
#include <map>
#include <vector>
using namespace std;
typedef unsigned long long ulint;
typedef pair<ulint, ulint> Hash;
#define maxn (40100)
const ulint seed = 30007uLL;
const ulint mod1 = 100007;
const ulint mod2 = 1e9 + 1017uLL;
ulint xp1[maxn], H1[maxn], xp2[maxn], H2[maxn];

int m, slen;
char s[maxn];

ulint h1[mod1], h2[mod1];
int t[mod1], vis[mod1];

pair<int, int> check(int len)
{
    memset(t, 0, sizeof(t));
    memset(vis, 0, sizeof(vis));
    int ans = -1;

    H1[0] = H2[0] = s[0] - 'a' + 1;
    for(int i = 1; i < len; i++)
    {
        H1[i] = (H1[i-1] * seed + s[i] - 'a' + 1) % mod1;
        //printf("H1[%d] = %llu\n", i, H1[i]);
        H2[i] = (H2[i-1] * seed + s[i] - 'a' + 1) % mod2;
        //printf("H2[%d] = %llu\n", i, H2[i]);
    }
    vis[H1[len-1]] = 1;
    h1[H1[len-1]] = H1[len-1];
    h2[H1[len-1]] = H2[len-1];
    t[H1[len-1]]++;
    if(t[H1[len-1]] >= m) ans = 0;

    for(int i = len; i < slen; i++)
    {
        H1[i] = ((H1[i-1] + mod1) - ((s[i-len] - 'a' + 1) * xp1[len-1]) % mod1) % mod1;
        H1[i] = (H1[i] * seed + s[i] - 'a' + 1) % mod1;

        H2[i] = ((H2[i-1] + mod2) - ((s[i-len] - 'a' + 1) * xp2[len-1]) % mod2) % mod2;
        H2[i] = (H2[i] * seed + s[i] - 'a' + 1) % mod2;

        int pos = H1[i];
        while(vis[pos] && (h1[pos] != H1[i] || h2[pos] != H2[i]))
        {
            pos = (pos + 1) % mod1;
        }
        vis[pos] = 1;
        h1[pos] = H1[i];
        h2[pos] = H2[i];
        t[pos]++;

        if(t[pos] >= m) ans = i + 1 - len;
    }

    return make_pair(len, ans);
}

int main()
{
    //freopen("4080.txt", "r", stdin);

    xp1[0] = xp2[0] = 1uLL;
    for(int i = 1; i < maxn; i++)
    {
        xp1[i] = (xp1[i-1] * seed) % mod1;
        xp2[i] = (xp2[i-1] * seed) % mod2;
    }

    while((cin >> m) && m)
    {
        scanf("%s", s);
        slen = strlen(s);

        int l = 1, r = slen, m;

        pair<int, int> ans = make_pair(0, -1);

        while(l <= r)
        {
            m = (l + r) >> 1;

            pair<int, int> ret = check(m);

            if(ret.second < 0) r = m - 1;
            else
            {
                ans = ret;
                l = m + 1;
            }
        }

        if(ans.second < 0) cout << "none" << endl;
        else cout << ans.first << " " << ans.second << endl;
    }

    return 0;
}
版权声明:想转就转吧,反正也是人人都会的东西:-( 举报

相关文章推荐

ACM hash哈希字符串 模板 hdu4080

先二分长度,然后用hash来查询

【字符串哈希】 HDOJ 4080 Stammering Aliens

这道题用字符串哈希较慢。。。。C++超时。。。G++AC。。。 #include #include #include #include #include #includ...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

HDU4080后缀数组

出现K次或K次以上最长子串,并且输出最右边的子串首字母坐标。 和之前总结的一个题一样,二分长度,找到统计height数组大于等于K的个数,满足返回true;这里因为还要找最右边子串首字母坐标,因而需...

HDU 4080 UVaLive 4513 - Stammering Aliens (字符串hash)

Stammering Aliens Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot...

网易云课堂 浙江大学-陈越、何钦铭-数据结构基础习题集(自测)

题目链接:http://www.patest.cn/contests/mooc-ds 【打印沙漏】 #include #include #include using namespace std;...

hdu 4080 Stammering Aliens 二分 hash

POJ 3882 TLE 需后缀数组 ------------ const int SEED = 13331; const int MAX_N = 50000 + 10; char s[MAX_N...

HDU 4080 Stammering Aliens(后缀数组+二分)

Description 给出一个字符串,求这个字符串中重复次数不少于m次的最长字串长度以及这个子串在原串中最后一次出现的位置 Input 多组用例,每组用例第一行为一整数m,第二行为一长度不超过...
  • V5ZSQ
  • V5ZSQ
  • 2016-05-05 22:23
  • 347

[HDU 4080] Stammering Aliens (字符串哈希+二分)

链接HDU 4080题意每组数据为一个整数m和一个长度不小于m的字符串,求该字符串的一个子串,该子串在满足出现次数不小于m的同时应尽量长。 输出该长度和最右侧出现的起始位置。如果存在多组数据,输出有...

HDU 4080 Stammering Aliens

刚开始直接把一个全局变量直接在函数里面赋值,结果一直WA 后来学乖了,里面用函数返回值把值传出来,就AC了 以后还是尽量少用全局变量吧,尤其是在有循环的地方,往往容易出错 还摸索出一个对付WA的...

HDOJ 4080 Stammering Aliens

用hash挫字符串。。。。 Stammering Aliens Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 327...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)