牛客网暑期ACM多校训练营(第三场)E hash解法



题意:
给一个字符串,复制前n-1个字符后,问有多少种长度n的子串,分类后按字典序输出下标。

题解:

复制一遍字符串,然后预处理hash表。之后for每个起始位置,可以在O(1)的时间获取子串的hash值,然后扔进map分类即可。对于这种写法字典序不需要特殊处理。
这个题卡常…有两个点要注意一下。
1.mod取1e9+7会冲突(过了62.5%的数据),而且每次%常数很大,会tle,这里选用了ull(自动%2^64)。

2.要用unordered_map,不然会tle。

代码:
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define mem(a,b) memset((a),(b),sizeof(a))
#define MP make_pair
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define all(x) x.begin(),x.end()
using namespace __gnu_cxx;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef vector<int> VI;
typedef vector<ll> VL;
const int INF=0x3f3f3f3f;
const ll LLINF=0x3f3f3f3f3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-6;
const int MAX=2e6+10;
const ll mod=1e9+7;
/*********************************  head  *********************************/
struct hash_table
{
    ull seed;
    ull Hash[MAX],tmp[MAX];
    void set(ull _seed)
    {
        seed=_seed;
    }
    void work(char *s,int n)
    {
        ll i,j;
        tmp[0]=1;
        Hash[0]=0;
        for(i=1;i<=n;i++) tmp[i]=tmp[i-1]*seed;
        for(i=1;i<=n;i++) Hash[i]=(Hash[i-1]*seed+(s[i]-'a'));
    }
    ull get(int l,int r)
    {
        return (Hash[r]-Hash[l-1]*tmp[r-l+1]);
    }
}h;
char s[MAX];
VI res[MAX];
int main()
{
    int i,j,len,tot;
    while(~scanf("%s",s+1))
    {
        len=strlen(s+1);
        for(i=len+1,j=1;j<=len;i++,j++) s[i]=s[j];
        h.set(23333);
        h.work(s,len*2);
        unordered_map<ull,int> mp;
        tot=0;
        for(i=1;i<=len;i++)
        {
            ull tmp=h.get(i,i+len-1);
            if(!mp.count(tmp)) mp[tmp]=++tot;
            res[mp[tmp]].pb(i-1);
        }
        printf("%d\n",tot);
        for(i=1;i<=tot;i++)
        {
            printf("%d",sz(res[i]));
            for(auto it:res[i]) printf(" %d",it);
            puts("");
            res[i].clear();
        }
    }
    return 0;
}


全部评论
双hash+unordered_map  T了  然后手写了hash_table才过...
点赞 回复 分享
发布于 2018-07-27 08:52
我试了下把23333改成其他的都TLE了...
点赞 回复 分享
发布于 2018-07-27 00:13
应该是像23333这样的5位数刚好取模的时候运算比较快,我试了换成19873也过了
点赞 回复 分享
发布于 2018-07-27 08:29
话说换成unorder_map还怎么保证是字典序?
点赞 回复 分享
发布于 2018-07-27 08:31
今天试了一下,超出内存限制啊QAQ
点赞 回复 分享
发布于 2018-07-27 10:29

相关推荐

10-11 17:45
门头沟学院 Java
走吗:别怕 我以前也是这么认为 虽然一面就挂 但是颇有收获!
点赞 评论 收藏
分享
11-15 17:19
湖南大学 Java
成果成果成果果:这是哪个公司的hr,这么离谱吗,我没见过用性别卡技术岗的,身边女性同学拿大厂offer的比比皆是
点赞 评论 收藏
分享
2 收藏 评论
分享
牛客网
牛客企业服务