BZOJ 4166: 月宫的符卡序列

如果使用回文树,节点 \(u\) 的回文串和 \(fail_u\) 的回文串中心不一样,因为回文树的 \(fail\) 指针指向的是最长回文后缀,没法快速解决异或和
考虑魔改回文树,用马拉车来解决,扩展的时候用字符串哈希和哈希表来得到每个节点,连接fail指针,就做完了

#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define pii pair<ll, int>
#define lp p << 1
#define rp p << 1 | 1
#define mid ((l + r) >> 1)
#define lowbit(i) ((i) & (-i))
#define ll long long
#define ull unsigned long long
#define db double
#define rep(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=b-1;i>=a;i--)
#define Edg int ccnt=1,head[N],to[N*2],ne[N*2];void addd(int u,int v){to[++ccnt]=v;ne[ccnt]=head[u];head[u]=ccnt;}void add(int u,int v){addd(u,v);addd(v,u);}
#define Edgc int ccnt=1,head[N],to[N*2],ne[N*2],c[N*2];void addd(int u,int v,int w){to[++ccnt]=v;ne[ccnt]=head[u];c[ccnt]=w;head[u]=ccnt;}void add(int u,int v,int w){addd(u,v,w);addd(v,u,w);}
#define es(u,i,v) for(int i=head[u],v=to[i];i;i=ne[i],v=to[i])
const int MOD = 1e9 + 7;
void M(int &x) {if (x >= MOD)x -= MOD; if (x < 0)x += MOD;}
int qp(int a, int b = MOD - 2) {int ans = 1; for (; b; a = 1LL * a * a % MOD, b >>= 1)if (b & 1)ans = 1LL * ans * a % MOD; return ans % MOD;}
int gcd(int a, int b) { while (b) { a %= b; std::swap(a, b); } return a; }

const int N = 2e6 + 7;

struct Hash {
	int base[N];
	int seed, MOD;
	int ha[N];
	void setseed(int x) { seed = x; }
	void setmod(int x) { MOD = x; }
	void init() {
		for (int i = base[0] = 1; i < N; i++)
			base[i] = 1LL * base[i - 1] * seed % MOD;
	}
	void init(char *s, int n) {
		ha[0] = 0;
		rep (i, 1, n + 1) ha[i] = (1LL * ha[i - 1] * seed + s[i]) % MOD;
	}
	int get(int l, int r) {
		return (ha[r] - 1LL * ha[l - 1] * base[r - l + 1] % MOD + MOD) % MOD;
	}
	int get(int l, int r, int x, int y) {
		int la = get(l, r), ra = get(x, y);
		return (1LL * la * base[y - x + 1] + ra) % MOD;
	}
} H, T;
ull hv(int l, int r) {
	return ((ull)H.get(l, r) << 31LL) + T.get(l, r);
}
int tol;
struct HashTable {
	static const int mod = 1e6 + 7;
	struct E {
		ull x;
		int ne, id;
	} e[mod + 7];
	int head[mod + 7], cnt;
	void clear() { cnt = 0; memset(head, 0, sizeof head); }
	int ins(ull x) {
		int u = x % mod;
		e[++cnt].x = x; e[cnt].ne = head[u]; e[cnt].id = ++tol; head[u] = cnt;
		return tol;
	}
	int query(ull x) {
		int u = x % mod;
		for (int i = head[u]; i; i = e[i].ne) if (e[i].x == x) return e[i].id;
		return 0;
	}
} mp;
char str[N], s[N];
int ma[N], sum[N], fail[N];
void init() {
	tol = 0; mp.clear();
}
void solve() {
	scanf("%s", str + 1);
	int n = strlen(str + 1);
	H.init(str, n); T.init(str, n);
	int len = 0;
	s[len] = '@'; s[++len] = '#';
	rep (i, 1, n + 1) s[++len] = str[i], s[++len] = '#';
	s[len + 1] = 0;
	int mx = 0, id = 0;
	rep (i, 1, len + 1) {
		ma[i] = (mx > i) ? (std::min(mx - i, ma[id * 2 - i])) : 1;
		int last = ma[i] == 1 ? 0 : (mp.query(hv((i - ma[i] >> 1) + 1, i + ma[i] - 1 >> 1)));
		while (s[i - ma[i]] == s[i + ma[i]]) {
			ma[i]++;
			int cur = mp.query(hv((i - ma[i]) / 2 + 1, i + ma[i] - 1 >> 1));
			if (!cur) {
				cur = mp.ins(hv((i - ma[i]) / 2 + 1, i + ma[i] - 1 >> 1));
				fail[cur] = last; sum[cur] = 0;
			}
			last = cur;
		}
		if (last) sum[last] ^= i / 2 - 1;
		if (i + ma[i] > mx) mx = i + ma[i], id = i;
	}
	int ans = 0;
	per (i, 1, tol + 1) ans = std::max(ans, sum[i]), sum[fail[i]] ^= sum[i];
	printf("%d\n", ans);
}

int main() {
	H.setseed(233); H.setmod(998244353);
	T.setseed(2333); T.setmod(19260817);
	H.init(); T.init();
	int T;
	scanf("%d", &T);
	while (T--) init(), solve();
}
posted @ 2020-02-28 14:15  Mrzdtz220  阅读(113)  评论(0编辑  收藏  举报