循环同构字符串 字符串哈希
题目
白兔的字符串(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|<=10 ^ 7),max(|S1|,|S2|,|S3|,|S4|,..|Sn|)<=10 ^ 6
输出描述:
输出n行表示每个串的答案
示例1
输入
abab
2
abababab
ababcbaba
输出
5
2
思路
循环同构,我们吧T环拆链,然后保存所有的循环同构字符串字符串哈希就可以了。
对于查询查询长度为|T|的哈希值的是否存在就可以了。
坑点:要自然溢出才能A。
#include <bits/stdc++.h>
#define uLL unsigned long long
#define LL long long
using namespace std;
const int maxn=2000005;
struct Hash_char {
uLL base=131;
uLL p[maxn], g[maxn];
void getp() {
p[0]=1;
for(int i=1; i<maxn; i++) {
p[i]=p[i-1]*base;
}
}
uLL Hash(char s[]) {
int len=strlen(s+1);
g[0]=0, g[1]=s[1];
for(int i=2; i<=len; i++) {
g[i]=(g[i-1]*base+s[i]);
}
return g[len];
}
uLL getLR(int l, int r) { //得到s[l]-s[r]的hash值
uLL ans=(g[r]-g[l-1]*p[r-l+1]);
return ans;
}
} hc, hd;
struct HashMap { //拉链法hash表
static const int MXSZ = 1e7 + 100; //元素总数 查询也会创建元素 能开大就开大
static const int MOD = 1e6 + 3; //1e3+9 1e4+7 1e6+3 1e7+19 1e8+7
struct node {
uLL key, val;
int nxt;
} elem[MXSZ];
int head[MOD], tot;
void init() { //注意初始化!!!
tot = 0;
memset(head, -1, sizeof(head));
}
bool count(uLL key){
int k = key % MOD;
for (int i = head[k]; ~i; i = elem[i].nxt)
if (elem[i].key == key)
return 1;
return 0;
}
uLL& operator [] (uLL key) {
int k = key % MOD; //取模位置
for (int i = head[k]; ~i; i = elem[i].nxt)
if (elem[i].key == key) //key相等
return elem[i].val; //返回val引用
elem[tot].key = key, elem[tot].nxt = head[k], head[k] = tot; //新建项 将原有的接在当前后并记录当前
return elem[tot++].val = 0; //清空值并返回引用
}
}mp;
char s[maxn];
int main() {
hc.getp(); hd.getp(); mp.init();
scanf("%s", s+1);
int N=strlen(s+1);
for(int i=1; i<=N; i++) s[N+i]=s[i];
hc.Hash(s);
for(int i=1; i<=N; i++){
mp[hc.getLR(i, i+N-1)]=1;
}
int t;
scanf("%d", &t);
while(t--) {
scanf("%s", s+1);
int len=strlen(s+1);
if(len<N){
printf("0\n"); continue;
}
hd.Hash(s);
int ans=0;
for(int i=1; i<=len-N+1; i++){
uLL res=hd.getLR(i, i+N-1);
if(mp.count(res)){
ans++;
}
}
printf("%d\n", ans);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了