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 * */