HDU 5769 Substring (后缀数组)
2017-07-19 12:47
351 查看
题意:给你一个字符c和一个字符串s,问你s的所有不同子串中有多少个子串含有c。
思路:做过求不同子串个数打开链接,是∑n-sa[i]-height[i], 现在要求子串中含有c,无非是每次计算从含有c的前缀开
始计算。预处理记录下每个位置向后最近的c的位置。这样答案就是∑n-max(p[sa[i]], sa[i]+height[i])
代码:
思路:做过求不同子串个数打开链接,是∑n-sa[i]-height[i], 现在要求子串中含有c,无非是每次计算从含有c的前缀开
始计算。预处理记录下每个位置向后最近的c的位置。这样答案就是∑n-max(p[sa[i]], sa[i]+height[i])
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int maxn = 1e5+5; int t1[maxn], t2[maxn], c[maxn]; int ra[maxn], height[maxn]; int sa[maxn]; char str[maxn]; bool cmp(int *r, int a, int b, int l) { return r[a]==r[b]&&r[a+l]==r[b+l]; } void da(char str[], int sa[], int ra[], int height[], int n, int m) { n++; int i, j, p, *x = t1, *y = t2; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[i]=str[i]]++; for(i = 1; i < m; i++) c[i] += c[i-1]; for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i; for(j = 1; j <= n; j<<=1) { p = 0; for(i = n-j; i < n; i++) y[p++] = i; for(i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i]-j; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[y[i]]]++; for(i = 1; i < m; i++) c[i] += c[i-1]; for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1; x[sa[0]] = 0; for(i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++; if(p >= n) break; m = p; } int k = 0; n--; for(i = 0; i <= n; i++) ra[sa[i]] = i; for(i = 0; i < n; i++) { if(k) k--; j = sa[ra[i]-1]; while(str[i+k]==str[j+k]) k++; height[ra[i]] = k; } } int p[maxn]; int main(void) { int t, ca = 1; cin >> t; while(t--) { char tch[2], ch; scanf(" %s", tch); ch = tch[0]; scanf(" %s", str); int n = strlen(str); da(str, sa, ra, height, n, 127); int pos = n; for(int i = n-1; i >= 0; i--) { if(str[i] == ch) pos = i; p[i] = pos; } ll ans = n-p[sa[1]]; for(int i = 2; i <= n; i++) { int r = max(p[sa[i]], sa[i]+height[i]); ans += n-r; } printf("Case #%d: %lld\n", ca++, ans); } return 0; }
相关文章推荐
- HDU 5769 Substring(后缀数组)
- HDU 5769 Substring(后缀数组)
- HDU 5769 Substring(后缀数组)
- HDU 5769 Substring(后缀数组)
- HDU 5769 Substring (后缀数组)
- HDU 5769 Substring(后缀数组)
- hdu 5769 Substring 后缀数组
- HDU 5769 Substring 多校赛 (后缀数组)
- HDU 5769 Substring(后缀数组)
- HDU 5769 Substring (后缀数组)
- HDU-5769-Substring(后缀数组)
- hdu_5769_Substring(后缀数组)
- hdu 5769 Substring 后缀数组
- poj - 2774 - Long Long Message / hdu - 1403 - Longest Common Substring(后缀数组)
- poj2774 Long Long Message && hdu 1403 Longest Common Substring 最长公共字串【后缀数组(倍增)】
- hdu 1403 Longest Common Substring(最长公共子字符串)(后缀数组)
- HDU 5769 Substring
- hdu 5769 Substring 2016 多校第四场
- 后缀数组 POJ 3693 && hdu 2459 Maximum repetition substring
- Hdu-5769 Substring (SA后缀数组)