UVA - 12206 Stammering Aliens (hash)

这题其实很容易想到2分长度,关键是2分后,怎么判断出现最多次的串是否》=m次了。这里需要用到hash来处理。 对于一个字符串   H[i] =H[i+1]*131+s[i]  ;其中 H[n]=0;那么对于一个长度为L的串 ,hanh[i,l]=H[i]-H[i+L]*x^L ; 这样记录每个字符串的hash值,然后再处理起来就比较简单了。

VIEW CODE

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstring>
#include<map>
#include<vector>
#include<set>
#include<ctime>
#include<stdlib.h>
using namespace std;
const int mmax= 1000010;
const int mod=1000000007;
const int inf=0x3fffffff;
using namespace std;
typedef long long  LL;
typedef unsigned long long ULL;
ULL H[mmax];

map<ULL,int>q;
int m;
char str[mmax];
ULL Pow[mmax];
void build_ha()
{
    int n=strlen(str);
    H[n]=0;
    for(int i=n-1;i>=0;i--)
        H[i]=H[i+1]*131+str[i];
}
ULL Ha[mmax];
bool ok(int k)
{
    int n=strlen(str);
    for(int i=0;i+k-1<n;i++)
    {
        ULL tmp=H[i]-H[i+k]*Pow[k];
        Ha[i]=tmp;
    }
    sort(Ha,Ha+n-k+1);
    int cnt=0;
    for(int i=0;i<n-k+1;i++)
    {
        if( i && Ha[i]==Ha[i-1])
            cnt++;
        else
        {
            if(cnt>=m)
                return 1;
            cnt=1;
        }
    }
    if(cnt>=m)
        return 1;
    return 0;
}
int main()
{
    Pow[0]=1;
    for(int i=1;i<mmax;i++)
        Pow[i]=Pow[i-1]*131;
    while(cin>>m&&m)
    {
        scanf("%s",str);
        int n=strlen(str);
        int l=1,r=n+1;
        build_ha();
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(ok(mid))
                l=mid+1;
            else
                r=mid;
        }

        int ans=r-1;
        if(!ans)
        {
            puts("none");
            continue;
        }
        int e;
        q.clear();
        for(int i=0;i+ans-1<n;i++)
        {
            ULL tmp=H[i]-H[i+ans]*Pow[ans];
            q[tmp]++;
            if(q[tmp]>=m)
                e=i;
        }
        printf("%d %d\n",ans,e);
    }
    return 0;
}
时间: 2024-10-13 22:28:57

UVA - 12206 Stammering Aliens (hash)的相关文章

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

Uva 12206 Stammering Aliens

题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 3 baaaababababbababbab 11 baaaababababbababbab 3 cccccc 0 输出样例#1: 5 12 none 4 2 这个题后缀数组或者二分+hash好像都能做,,,但是我只是练一下后缀自动机而已hhhhh这个题我们求的显然就是right集合大小>=m的max{}的最大值,至于求最右开端的话,我们只需要记录一下right集合的最右点是哪个就行了,然后用这个减去答案长度就是最右开

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

POJ 3026 Borg Maze &amp; UVA 10307 Killing Aliens in Borg Maze(BFS,最小生成树)

http://poj.org/problem?id=3026 http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1248 Borg Maze Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8498   Accepted: 2862 Description The Bor

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

UVA 11107 - Life Forms(Hash+LCP)

UVA 11107 - Life Forms 题目链接 题意:给定一个字符串,找出重复出现超过m次的字串的最大开始下标 思路:hash大法,需要点人品,然后二分答案,每次利用hash值去找出最大下标即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef unsigned long long ull; const ull x = 123; c

UVA 257 - Palinwords(字符串HASH)

UVA 257 - Palinwords 题目链接 题意:输出一个文本里面的palinword,palinword的定义为,包含两个不同的回文子串,并且要求回文子串不能互相包含 思路:对于每个单词判断一次,由于不能互相包含,对于每个位置,其实就只要找长度3和4的情况即可,这样复杂度为O(n),至于判断重复的,就用hash即可 代码: #include <cstdio> #include <cstring> char str[260]; int hash[555555], save[

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