E-Sort String 字符串hash+hash表做法

这题一开始就想到了要O(1)得到起始点为i(0~len-1)长度为len的每一个串的hash值,但是在这之后如果不能O(n)的在容器里将他们分类排序的话基本上就超时(sort排序超了凉凉);
用字符串hash将翻倍了的字符串hash一遍,然后O1得到每一个len长的串的hash值,将每一个很大的hash值用hash表存起来分配到vector里输出;
这题用了双hash,hash值里用到的INF如果是1e9的话还是有可能hash冲突的(就比如说我这个非洲人就wa了,别人交就过了。)


///耗时:817ms(菜鸡的代码,写的很挫)  内存使用:152288kb
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6+1e5+7, w=26;
const ll INF=2e9;///这个值为1e9可能还会有冲突
void write(int x){
    if(x==0){putchar(48);return;}
    int len=0,dg[20];
    while(x>0){dg[++len]=x%10;x/=10;}
    for(int i=len;i>=1;i--)putchar(dg[i]+48);
}
int len, cnt;
struct has
{
    ll P;
    ll mi_w[maxn];
    ll hs[maxn];
    void init(char *s)
    {
        P=1e9+rand();
        mi_w[0]=1;
        for(int i=1; i<=len; i++)
            mi_w[i]=mi_w[i-1]*w%P;
        for(int i=1; i<=len; i++)
            hs[i]=(hs[i-1]*w+s[i]-'0')%P;
    }
    ll get(int l,int r)
    {
        return ((hs[r]-hs[l-1]*mi_w[r-l+1])%P+P)%P;
    }
    bool ok(int l,int r)
    {
        return (get(1,l)+get(l+1,r)-get(r+1,len))%P==0;
    }
}h[2];
const int Size=2333237;///hash表用的mod
struct Hash{
    int num[Size];
    ll key[Size];
    void init(){
        memset(num, 0, sizeof(num));
        memset(key, -1, sizeof(key));
    }
    int Insert(ll x){
        int num1=x%Size;
        while(key[num1]!=-1){
            if(key[num1]==x){
                return num[num1];
            }
            ++num1;
            if(num1>=Size)
                num1-=Size;
        }
        key[num1]=x;
        num[num1]=cnt++;
        return num[num1];
    }
}th;
char str[maxn];
vector<int> vv[maxn/2];
int main(){
    register int j, i, slen, top, sav;
    register ll aaa;
    srand(time(0));
    scanf("%s", str+1);
    len=slen=strlen(str+1);
    th.init();
    len*=2;
    for(i=1;i<=slen;++i)///翻倍
        str[i+slen]=str[i];
    h[0].init(str);
    h[1].init(str);
    cnt=0;
    for(i=1; i<=slen; ++i){
        aaa=h[0].get(i, i+slen)*INF+h[1].get(i, i+slen);
        sav=th.Insert(aaa);///插入的时候如果插入过这个数字就返回保存的下标值,没插入过就返回新保存的下标值
        vv[sav].push_back(i-1);
    }
    write(cnt);
    putchar('\n');
    for(i=0; i<cnt; ++i){
        sav=vv[i].size();
        write(sav);
        for(j=0; j<sav; ++j)
            putchar(' '), write(vv[i][j]);
        putchar('\n');
    }
}
用next数组找循环节的方法刚刚补了一下,果然快了好多;

耗时:138ms   内存使用:14056kb 
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+7;
int Next[N];
void write(int x){
    if(x==0){putchar(48);return;}
    int len=0,dg[20];
    while(x>0){dg[++len]=x%10;x/=10;}
    for(int i=len;i>=1;i--)putchar(dg[i]+48);
}
void getNext(char *s, int &len){
    Next[0]=-1;
    register int i=0,k=-1;
    while(i<len){
        if(k==-1||s[i]==s[k]){
            Next[++i]=++k;
        }
        else{
            k=Next[k];
        }
    }
}
char str[N];
int main(){
    register int i, j, len, cnt;
    scanf("%s", &str);
    len=strlen(str);
    getNext(str, len);
    if(len%(len-Next[len])==0&&Next[len]){
        cnt=len-Next[len];
        write(len-Next[len]);
        putchar('\n');
        for(i=0; i<cnt; ++i){
            write(len/(len-Next[len]));
            for(j=i; j<len; j+=cnt){
                putchar(' ');
                write(j);
            }
            putchar('\n');
        }
    }else{
        write(len);
        putchar('\n');
        for(i=0; i<len; ++i){
            putchar('1');
            putchar(' ');
            write(i);
            putchar('\n');
        }
    }
}

全部评论

相关推荐

#简历#先说一说我自己的想法,很多人都很排斥苍穹外卖,认为没什么技术点和含金量,但实际上我觉得恰恰相反,苍穹外卖虽然代码本身并不是你自身能力的证明,但是是作为一个新人学习时很好的跳板和原始框架,在这个框架上进行的改进可以很好的辐射到你自己的个人成果上,并作为你和面试官聊天的筹码大多数人的苍穹外卖只写增删改查,千篇一律,吸引不了面试官,所以这才让大家误以为只要是苍穹外卖就不要写进简历里这种误区,但实际上如果你在原有的层面上进行改进,并作为你的项目亮点和面试官介绍,告诉他你的苍穹外卖和别人的有什么不同,增加了哪些技术难点,这才显得你是完全自己理解了这个项目,并且有自己动手实践项目的能力,而不是就看了个课程就以为自己会了,就当成自己的了,如此一来,这反而成为你的加分项苍穹外卖为什么看的人最多,说明它好啊,如果它不好,为什么看的人还这么多,想清楚这个逻辑,我觉得要做的最重要的事,就是如何在原有框架上进行改进提效,比起听其他人的话重新搞一个项目性价比高得多,而且我亲测项目并没有成为我找到工作的阻碍,我投的大厂一大半都给我面试了,而且很多不止一个部门,退一万步说,当你手头没有其他项目的时候,有苍穹外卖总比什么都没有的好很多,不需要因为苍穹外卖有任何心理负担关于简历的任何部分都欢迎大家提意见,十分感谢大家,祝大家找实习+秋招顺利上岸,offer拿到手软#简历中的项目经历要怎么写##我的上岸简历长这样##最后再改一次简历##简历##简历被挂麻了,求建议#
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务