Stammering Aliens 【二分+哈希】

来源:互联网 发布:淘宝防举报神盾 编辑:程序博客网 时间:2024/06/14 15:56

题目链接:

https://odzkskevi.qnssl.com/0187fdccf71569bb074542c4463bea64?v=1508888740

题意:

给你一个整数n和一串字符串,求最长出现至少n次的子串。
输出最长子串长度和最后一个子串的第一个字符位置。

做法:

1.二分长度求右界。
2.judge里hash,用map记录次数

#include <bits/stdc++.h>using namespace std;typedef unsigned long long ull;const int maxn = 40000;const int base = 131;char str[maxn + 10];ull hah[maxn + 10];ull f[maxn + 10];int n, len;unordered_map<ull,int>mp; //开全局比放在judge里快600msint judge(int x) {    mp.clear();    int cmp = 0, pos = -1;    for(int i = 0; i < len; ++ i) {        if(i + x - 1 >= len) break;        ull tmp_hah = hah[i + x - 1] - f[x] * hah[i - 1];        int tmp_mp = ++mp[tmp_hah]; //此处赋值给int,不用查两遍,实测速度快了近200ms        if(tmp_mp >= n) pos = i;    }    return pos;}void init() {    memset(hah, 0, (len + 2)*sizeof(ull));    hah[0] = str[0];    for(int i = 1; i < len; ++ i)        hah[i] = hah[i - 1] * base + str[i];}int main() {    f[0] = 1;    for(int i = 1; i < maxn + 10; ++ i)        f[i] = f[i - 1] * base;    while(~scanf("%d", &n) && n) {        scanf("%s", str);        len = strlen(str);        init();        if(judge(1) == -1) {            puts("none");            continue;        }        int low = 1, high = len;        while(low < high) {            int mid = low + high + 1 >> 1;            if(judge(mid) > -1) low = mid;            else high = mid - 1;        }        int pos = judge(low);  //可以开全局,少一次judge快近100ms        printf("%d %d\n", low, pos);    }}
原创粉丝点击