洛谷P5112 FZOUTSY
卡map还行.....手写hash表即可。
我一开始以为这个k会变......在sam上想各种奇技淫巧。
k不变就是问一段区间有多少对长度为k的子串相同。
然后hash把子串转化为数字,就是区间有多少对相同数字。直接莫队即可。
1 #include <bits/stdc++.h> 2 3 inline void read(int &x) { 4 x = 0; 5 char c = getchar(); 6 while(c < '0' || c > '9') c = getchar(); 7 while(c >= '0' && c <= '9') { 8 x = x * 10 + c - 48; 9 c = getchar(); 10 } 11 return; 12 } 13 14 typedef long long LL; 15 typedef unsigned long long uLL; 16 const int N = 3000010; 17 const uLL B = 13331; 18 19 uLL h[N], pw[N]; 20 std::map<uLL, int> mp; 21 int n, k, val[N], fr[N], bin[N]; 22 char str[N]; 23 LL ans[N], Ans; 24 25 namespace Map { 26 const int mod = 10000010; 27 struct Edge { 28 uLL val; 29 int num, nex; 30 }edge[N]; int tp; 31 int e[mod], num; 32 inline int insert(uLL v) { 33 int x = v % mod; 34 for(int i = e[x]; i; i = edge[i].nex) { 35 if(edge[i].val == v) return edge[i].num; 36 } 37 edge[++tp].val = v; 38 edge[tp].num = ++num; 39 edge[tp].nex = e[x]; 40 e[x] = tp; 41 return num; 42 } 43 } 44 45 struct Ask { 46 int l, r, id; 47 inline bool operator <(const Ask &w) const { 48 if(fr[l] != fr[w.l]) return l < w.l; 49 return r < w.r; 50 } 51 }ask[N]; 52 53 inline uLL Hash(int l, int r) { 54 return h[r] - h[l - 1] * pw[r - l + 1]; 55 } 56 57 inline void getHash() { 58 pw[0] = 1; 59 for(register int i = 1; i <= n; i++) { 60 pw[i] = B * pw[i - 1]; 61 h[i] = h[i - 1] * B + str[i]; 62 } 63 for(register int i = 1; i + k - 1 <= n; i++) { 64 uLL t = Hash(i, i + k - 1); 65 //printf("i = %d t = %llu \n", i, t); 66 val[i] = Map::insert(t); 67 //printf("val %d = %d \n", i, val[i]); 68 } 69 return; 70 } 71 72 inline void add(int x) { 73 Ans += bin[val[x]]; 74 bin[val[x]]++; 75 return; 76 } 77 78 inline void del(int x) { 79 bin[val[x]]--; 80 Ans -= bin[val[x]]; 81 return; 82 } 83 84 int main() { 85 int m; 86 read(n); read(m); read(k); 87 scanf("%s", str + 1); 88 int T = (double)n / sqrt(m); 89 for(register int i = 1; i <= m; i++) { 90 read(ask[i].l); read(ask[i].r); 91 ask[i].r = std::min(ask[i].r, n - k + 1); 92 ask[i].id = i; 93 } 94 for(register int i = 1; i <= n; i++) fr[i] = (i - 1) / T + 1; 95 std::sort(ask + 1, ask + m + 1); 96 getHash(); 97 98 int l = 1, r = 1; bin[val[1]] = 1; 99 for(register int i = 1; i <= m; i++) { 100 if(ask[i].l >= ask[i].r) { 101 ans[ask[i].id] = 0; 102 continue; 103 } 104 while(ask[i].l < l) { 105 add(--l); 106 } 107 while(r < ask[i].r) { 108 add(++r); 109 } 110 while(l < ask[i].l) { 111 del(l++); 112 } 113 while(ask[i].r < r) { 114 del(r--); 115 } 116 ans[ask[i].id] = Ans; 117 } 118 for(register int i = 1; i <= m; i++) printf("%lld\n", ans[i]); 119 return 0; 120 }