白兔的字符串(哈希)

白兔的字符串(哈希)

闲来无事学了下哈希,感觉上就是加密然后映射,下面直接上题目。
链接:https://ac.nowcoder.com/acm/problem/15253

题目描述

白兔有一个字符串T。白云有若干个字符串S1,S2…Sn。 白兔想知道,对于白云的每一个字符串,它有多少个子串是和T循环同构的。 提示:对于一个字符串a,每次把a的第一个字符移动到最后一个,如果操作若干次后能够得到字符串b,则a和b循环同构。 所有字符都是小写英文字母
输入描述:
第一行一个字符串T(|T|<=10^6)
第二行一个正整数n (n<=1000)
接下来n行为S1~Sn (|S1|+|S2|+…+|Sn|<=107),max(|S1|,|S2|,|S3|,|S4|,…|Sn|)<=106
输出描述:
输出n行表示每个串的答案

示例1

输入
abab
2
abababab
ababcbaba
输出
5
2

思路:将原先的字符串的所有循环同构的哈希值保存,然后每个查询就是直接查找是否存在该哈希值。我第一遍写的时候没注意会爆long long的情况,所以哈希值出现负的了,这里我们用unsigned long long就不会有这种情况了。

代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<map>
#include<set>
#define fi first
#define se second
#define pb push_back
#define me(a,b) memset(a,b,sizeof(a))
#define INIT() std::ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ll;//我只是懒得把下面的ll都改了,不要学我,还是用ull
typedef pair<int,int>P;
const int MAX_N=2000000+5;
const int INF=0x7fffffff;
const int inf=500000;
const double EPS=1e-6;
const ll base=123;
const ll mod=100007;
char s[MAX_N];
ll has[MAX_N];
ll h[MAX_N];
ll vis[MAX_N];
int viss[mod+5];
int pos=0;
struct node
{
   
    ll to;
    int next;
}rode[MAX_N];
void add(ll x)
{
   
    int xx=(int)(x%mod);
    rode[pos].to=x;
    rode[pos].next=viss[xx];
    viss[xx]=pos++;
}
int Find(ll x)
{
   
    int xx=(int)(x%mod);
    for(int i=viss[xx];i!=-1;i=rode[i].next)
    {
   
        if(rode[i].to==x)
            return 1;
    }
    return 0;

}
int main (void)
{
   
    memset(viss,-1,sizeof(viss));
    scanf("%s",s+1);
    int len=strlen(s+1);
    h[0]=(ll)1;
    int i;
    for(i=1;i<=2*len;i++)
    {
   
        h[i]=h[i-1]*base;
    }
    for(i=1;i<=len;i++)
    {
   
        s[len+i]=s[i];
    }
    for(i=1;i<=2*len;i++)
    {
   
        has[i]=base*has[i-1]+s[i]-'a';
        if(i>=len) add(has[i]-has[i-len]*h[len]);
    }

    int n;
    scanf("%d",&n);
    while(n--)
    {
   
        scanf("%s",s+1);
        int ans=0;
        has[0]=(ll)0;
        int l=strlen(s+1);
        for(i=1;i<=l;i++)
        {
   
            has[i]=has[i-1]*base+s[i]-'a';
            if(i>=len)
                ans+=Find(has[i]-has[i-len]*h[len]);
        }
        cout<<ans<<endl;
    }
}
全部评论

相关推荐

明明就不饿:看不懂你到底会啥,什么岗位
点赞 评论 收藏
分享
今天周一休息,突发奇想写一篇阶段总结。如题,我已经去了一个和Java彻底毫无关联的行业。曾经我以为自己能在计算机行业发光发热,没想到刚入行一年多就当了逃兵。从最开始的热爱到现在一看到代码就厌恶,不知道自己经历了什么。所以我去干什么了?答案是:在成都当了租房销售。上班那会压力大了就念叨着去干租房中介,但是一直下不去这个决心,想着自己学了四年多的计算机知识,终究还是不甘心。终于在某一天准备八股文的时候,看着无数篇和工作内容关系不大的理论知识,那一刻下定决心,决定尝试一下销售行业,也算是给自己一个交代。后面阴差阳错的投了成都自如去当租房管家,没想到面试很顺利,在当天一百多个面试的人里面,我成为了为数不多通过的几个幸运儿之一。目前已经培训通过,正式入职,也开了单,也有压力但是每天过得很开心,真心喜欢那种和人交流的感觉,哪怕是最后没有选择找我租房。说这些也是想告诉那些大三,大四正在找Java实习而焦虑的同学:你们现在还年轻,选择很多,容错率也很高,可以尽情去尝试自己喜欢的行业和工作。不用因为某一次的面试没通过或者简历石沉大海而焦虑,更不用因为身边人都在挤编程的独木桥就强迫自己跟风。也算是自己的碎碎念吧,也希望自己能在新的领域取得一点小成就。也祝牛油工作顺利!
沉淀小子:干啥都不丢人啊,生存是必须要的,销售很考验一个人综合素质能力的,好的销售人脉和资源可不比写字楼的白领差啊
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务