HDOJ 5769 Substring
来源:互联网 发布:逆袭网络宣传平台 编辑:程序博客网 时间:2024/05/12 09:28
题意
求一个字符串有多少个不同的子串,要求这些子串都包含至少一次x字符。
思路
如果不考虑包含x字符的话,求不同子串个数是一个后缀数组经典问题(spoj 694)。考虑那个问题的做法:
我用之前那个题的代码改了一下结果TLE了。后来发现是板子的问题,挑战程序设计竞赛的板子使用的快排(出题人竟然卡这个。。话说这个板子A了很多题了这是第一次被卡= =
然后换成大白书上的过了。
代码
#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;#define LL long long#define Lowbit(x) ((x)&(-x))#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1|1#define MP(a, b) make_pair(a, b)const int INF = 0x3f3f3f3f;const int MOD = 1000000007;const int maxn = 1e5 + 10;const double eps = 1e-8;const double PI = acos(-1.0);typedef pair<int, int> pii;//int temp[maxn], lcp[maxn];char x[2];char str[maxn];int nxt[maxn];int sa[maxn], rk[maxn], height[maxn];int c[maxn], t[2][maxn], s[maxn];void build(int n, int m) { int i, k, p, *x = t[0], *y = t[1]; memset(c, 0, m << 2); for(i = 0; i < n; ++i) ++c[x[i] = s[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(k = 1; k <= n; k <<= 1) { p = 0; for(i = n - k; i < n; ++i) y[p++] = i; for(i = 0; i < n; ++i) if(sa[i] >= k) y[p++] = sa[i] - k; memset(c, 0, m << 2); 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]] = (y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k]) ? p - 1 : p++; if(p >= n) break; m = p; } for(i = 0; i < n; ++i) rk[sa[i]] = i; for(i = 0, k = 0; i < n; ++i) { if(k) k--; if(!rk[i]) continue; int j = sa[rk[i] - 1]; while(s[i + k] == s[j + k]) k++; height[rk[i]] = k; }}//int compare_sa(int i, int j)//{// if (rk[i] != rk[j]) return rk[i] < rk[j];// else// {// int ri = i + k <= n ? rk[i+k] : -1;// int rj = j + k <= n ? rk[j+k] : -1;// return ri < rj;// }//}////void construct_sa(char *s, int *sa)//{// for (int i = 0; i <= n; i++)// {// sa[i] = i;// rk[i] = i < n ? s[i] : -1;// }// for (k = 1; k <= n; k *= 2)// {// sort(sa, sa + n + 1, compare_sa);// temp[s[0]] = 0;// for (int i = 1; i <= n; i++)// temp[sa[i]] = temp[sa[i-1]] + (compare_sa(sa[i-1], sa[i]) ? 1 : 0);// for (int i = 0; i <= n; i++)// rk[i] = temp[i];// }//}////void construct_lcp(char *s, int *sa, int *lcp)//{// for (int i = 0; i <= n; i++) rk[sa[i]] = i;// int h = 0;// lcp[0] = 0;// for (int i = 0; i < n; i++)// {// int j = sa[rk[i] - 1];// if (h > 0) h--;// for (; j + h < n && i + h < n; h++)// if (s[j+h] != s[i+h]) break;// lcp[rk[i] - 1] = h;// }//}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int T; scanf("%d", &T); for (int ncase = 1; ncase <= T; ncase++) { scanf("%s%s", x, str); int n = strlen(str); for (int i = 0; i < n; i++) s[i] = str[i] - 'a' + 1; s[n] = 0; build(n + 1, 30); nxt[n] = n; for (int i = n - 1; i >= 0; i--) { nxt[i] = nxt[i+1]; if (str[i] == x[0]) nxt[i] = i; } LL ans = 0; for (int i = 1; i <= n; i++) { //printf("%d %d %d %d\n", i, sa[i], height[i], nxt[sa[i]]); ans += n - max(sa[i] + height[i], nxt[sa[i]]); } printf("Case #%d: %lld\n", ncase, ans); } return 0;}
0 0
- HDOJ 5769 Substring
- hdoj 1238 (substring)
- HDOJ 1043 Longest Common Substring
- hdoj 5677 ztr loves substring
- HDOJ-5677 ztr loves substring
- 【后缀数组】 HDOJ 1403 Longest Common Substring
- HDOJ 1403:Longest Common Substring 后缀数组的用处
- 【后缀数组】 HDOJ 2459 && POJ 3693 Maximum repetition substring
- hdoj 5677 ztr loves substring 【Manacher + 多重背包】
- HDOJ 5677 ztr loves substring(Manacher+背包型DP)
- HDU 5769 Substring
- HDU 5769 Substring
- Substring
- Substring
- substring
- substring
- Substring
- substring
- 语法分析器之递归子程序法
- nefu504new Flip Game+高斯消元
- codeforces 43D Journey
- 华为高通携LTE技术杀入车联网,正面挑战V2X老标准
- Java:Session详解
- HDOJ 5769 Substring
- 「指针数组」和「数组指针」
- 面向对象思想的理解
- 1001. 害死人不偿命的(3n+1)猜想 (15)C++
- 【PHP】数组
- myeclipse 导入 svn项目
- 多线程下载图片的简单例子
- HDU 2444 二分图的判断和无向图的二分匹配
- NoClassDefFoundError 排查思路