CROC-MBTU 2012, Elimination Round (ACM-ICPC) H. Queries for Number of Palindromes

23 篇文章 2 订阅

Queries for Number of Palindromes

在这里插入图片描述
我们可以设 d p [ l ] [ r ] dp[l][r] dp[l][r] [ l , r ] [l,r] [l,r] 中 的答案。那么我们可以找到转移方程:
d p [ l ] [ r ] = d p [ l + 1 ] [ r ] + d p [ l ] [ r − 1 ] − d p [ l + 1 ] [ r − 1 ] + c h e c k ( l , r ) ( 判 断 整 个 [ l , r ] 是 不 是 回 文 串 ) dp[l][r] = dp[l+1][r]+dp[l][r-1]-dp[l+1][r-1]+check(l,r) (判断整个[l,r]是不是回文串) dp[l][r]=dp[l+1][r]+dp[l][r1]dp[l+1][r1]+check(l,r)[l,r]

那么关键就是判断一个串是否是回文串,也就是实现上面的 c h e c k ( l , r ) check(l,r) check(l,r) 。那么我们可以对字符串正反哈希两遍求得,然后我们就可以愉快的进行区间 d p dp dp 了。

#include <bits/stdc++.h>

using namespace std;

const int N = 5e3 + 10;

typedef unsigned long long ull;

int n, dp[N][N];

char s[N];

ull zhs[N], fhs[N], base = 233, b[N];
ull L(int l, int r) {return l > r ? 0 : zhs[r] - zhs[l - 1] * b[r - l + 1];}
ull R(int tl, int tr) {int l = n - tr + 1, r = n - tl + 1; return l > r ? 0 : fhs[r] - fhs[l - 1] * b[r - l + 1];}

void init() {
	b[0] = 1;
	for (int i = 1; i <= n; ++i) b[i] = b[i - 1] * base;
	for (int i = 1; i <= n; ++i) zhs[i] = zhs[i - 1] * base + s[i];
	reverse(s + 1, s + 1 + n);
	for (int i = 1; i <= n; ++i) fhs[i] = fhs[i - 1] * base + s[i];
}

bool check(int l, int r) {
	int mid = l + r >> 1;
	if ((r - l + 1) & 1) {
		return L(l, mid - 1) == R(mid + 1, r);
	}
	return L(l, mid) == R(mid + 1, r);
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	scanf("%s", (s + 1));
	n = strlen(s + 1);
	init();
	for (int len = 1; len <= n; ++len) {
		for (int l = 1, r; l + len - 1 <= n; ++l) {
			r = l + len - 1;
			dp[l][r] = dp[l + 1][r] + dp[l][r - 1] - dp[l + 1][r - 1] + check(l, r);
		}
	}
	int q; scanf("%d", &q);
	while(q--) {
		int l, r; scanf("%d%d", &l, &r);
		printf("%d\n", dp[l][r]);
	}
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值