迴圈同構字串 字串雜湊
阿新 • • 發佈:2020-12-09
題目
白兔的字串(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; }