hdu 3948 后缀数组统计不同回文串的个数
来源:互联网 发布:js时间差 编辑:程序博客网 时间:2024/05/28 15:57
字符串颠倒后接在后面,后缀数组排序,求回文串的时候分奇偶性讨论下就好了(也可以用Mancher 算法然后用多项式Hash 函数处理,这样应该是最快的)但是Hash函数一定要足够好,这里后缀数组相对保险一些吧,毕竟一个字符串的回文串数目不超过是o(n)级别的,后缀数组纵然是慢一些,也总能AC的
#include <utility>#include <algorithm>#include <string>#include <cstring>#include <cstdio>#include <iostream>#include <iomanip>#include <set>#include <vector>#include <cmath>#include <queue>#include <bitset>#include <map>#include <iterator>using namespace std;#define clr(a,v) memset(a,v,sizeof(a))#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int INF = 0x7f7f7f7f;const int maxn = 511111;const double pi = acos(-1.0);const double eps = 1e-10;typedef long long ll;typedef pair<int, int> pii;typedef vector<int> VI;typedef vector<VI> VVI;typedef vector<VVI> VVVI;char s[maxn];int a[maxn];int o[maxn];char buf[maxn];struct RMQ {int r[20][maxn];int i, j, k, n;void make(int a[]) {for (i = 0; i <= n; ++i)r[0][i] = a[i];for (i = 0; i < 19; ++i) {k = (1 << i);for (j = 0; j + k <= n; ++j) {r[i + 1][j] = min(r[i][j], r[i][j + k]);}}}int query(int L, int R) {j = R - L;i = 1, k = 0;while ((i << 1) < j)k++, i <<= 1;return min(r[k][L], r[k][R - i]);}} rmq;struct Suffix_Array {int wa[maxn], wb[maxn], wv[maxn], wn[maxn], h[maxn], sa[maxn], rank[maxn];bool cmp(int r[], int a, int b, int l) {return (r[a] == r[b] && r[a + l] == r[b + l]);}void Da(int r[], int n, int m) {int i, j, *t, *x = wa, *y = wb, p;for (i = 0; i < m; ++i)wn[i] = 0;for (i = 0; i < n; ++i)wn[x[i] = r[i]]++;for (i = 1; i < m; ++i)wn[i] += wn[i - 1];for (i = n - 1; i >= 0; --i)sa[--wn[x[i]]] = i;for (j = 1, p = 0; p < n; j <<= 1, m = p) {for (i = n - j, p = 0; 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 < n; ++i)wv[i] = x[y[i]];for (i = 0; i < m; ++i)wn[i] = 0;for (i = 0; i < n; ++i)wn[wv[i]]++;for (i = 1; i < m; ++i)wn[i] += wn[i - 1];for (i = n - 1; i >= 0; --i)sa[--wn[wv[i]]] = y[i];p = 1, t = x, x = y, y = t;for (x[sa[0]] = 0, i = 1; i < n; ++i) {x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;}}}void Calheight(int r[], int n) {int i, j, k = 0;for (i = 1; i <= n; ++i)rank[sa[i]] = i;for (i = 0; i < n; h[rank[i++]] = k)for (k ? k-- : k, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; ++k);}void print_sa(int n) {for (int i = 0; i <= n; ++i) {printf("%d %d %d %s\n", i, o[i], h[i], &s[sa[i]]);}}int LCP(int x, int y) {x = rank[x] + 1;y = rank[y] + 1;if (x > y)swap(x, y);return rmq.query(x, y);}int go(int n) {int i, p, ans = 0;int num = maxn << 1, cnt = maxn << 1;for (i = 1; i <= n; ++i) {p = sa[i];num = min(num, h[i]);if (~o[p]) {cnt = LCP(p, o[p]);if (cnt > num)ans += (cnt - num), num = cnt;}}num = maxn << 1;for (i = 1; i <= n; ++i) {p = sa[i];num = min(num, h[i]);if (~o[p]) {cnt = LCP(p, o[p] + 1);if (cnt > num)ans += (cnt - num), num = cnt;}}return ans;}} suffix;int main() {int i, n, len, j;int T, cas;scanf("%d", &T);for (cas = 1; cas <= T; ++cas) {scanf("%s", buf);len = strlen(buf);for (i = 0; i < len; ++i) {s[i] = buf[i];o[i] = -1;}s[len] = '$';for (i = len + 1, j = len - 1; j >= 0; --j, ++i) {s[i] = buf[j];o[i] = j;}s[n = i] = 0;for (i = 0; i <= n; ++i) {a[i] = (int) s[i];}suffix.Da(a, n + 1, 128);suffix.Calheight(a, n);rmq.n = n;rmq.make(suffix.h);printf("Case #%d: %d\n", cas, suffix.go(n));}return 0;}/* 5 abccccccccaaaaaaaabbbbbbb asdgdfgsdfgfdsgsdf dfsgsdfgsdgsdfgsdg aaaaaaaaaaaaaabbbbbbbbbbvcvvvvvvvvvvaabbbbaaa aaaaaaaaaaabbbbbbbbbbbbbbaaaaaaaaaaaacvccccccccccccvcaaa 23 13 5 38 56 * */
- hdu 3948 后缀数组统计不同回文串的个数
- hdu3948——后缀数组统计不同回文子串的个数
- hdu 3948 求不同回文串的个数
- spoj694 Distinct Substrings(后缀数组+统计不同子串的个数)
- HDU3948:后缀数组+马拉车(本质不同回文子串统计)
- 【后缀数组 不同的字串个数】SPOJ
- HDU 4622 本质不同的子串个数:后缀自动机
- hdu 5769后缀数组 求含有某个字母的某个字符串的不同子串的个数
- HDU 4436 str2int(后缀数组,一种统计n个digit字符串所有不同子串之和的方法)
- 后缀数组(不同的回文字串)hdu3948
- spoj 405 求不同子串的个数 后缀数组和高度数组的应用
- 回文树(统计所有回文串的个数)
- 【后缀数组】【不同子串个数】DISUBSTR spoj694/705
- spoj 694 Distinct Substrings(求不同的子串个数,后缀数组基础题)
- HDU4622:Reincarnation(后缀数组,求区间内不同子串的个数)
- SPOJ 题目694 Distinct Substrings(后缀数组,求不同的子串个数)
- SPOJ 题目705 New Distinct Substrings(后缀数组,求不同的子串个数)
- HDU 4622 Reincarnation(SAM 后缀自动机 求子串的不同子串个数)
- TX2440 裸跑实验-段分布图(ADS1.2编译) 补充知识
- JDBC CallableStatement IN/INOUT/OUT 参数
- 【洛奇】系列1
- 数据库事务
- 北漂,2013好好混
- hdu 3948 后缀数组统计不同回文串的个数
- 详细介绍如何搭建tftp服务器
- fork, vfork的区别
- 通向真实客户的数据之门——读《数据挖掘技术》第三版
- 黑马程序员——C#面向对象加强
- 万维网向公众开放20周年:全球首个网站重新上线
- utf8转换临时方法
- 杭电4144
- 基于FPGA的图像处理(七)--Verilog实现均值滤波