URAL 1989 Subpalindromes(线段树单点修改+字符串hash)
2015-08-22 17:03
337 查看
题意:
给出一个字符串,长度为10510^5,有m个操作m<=104m<= 10^4。有两种操作:
1. 询问[l,r][l,r]区间的子串是否回文
2. 将第ii个字符改为cc。
解析:
用字符串哈希+线段树来做这题,线段树用于查询区间的hash值。建两棵线段树一棵维护从前向后的hash值,另外一棵维护从后向前的hash值。
那么我们判断是否回文串,就只要看正反区间的哈希值之和是否相等就行了。
至于修改就是单点更新了。
mymy codecode
[code]#include <cstdio> #include <cstring> #include <algorithm> #define ls (o<<1) #define rs (o<<1|1) #define lson ls, L, M #define rson rs, M+1, R using namespace std; typedef unsigned long long ll; const int N = (int)1e5 + 10; const int sigma_size = 33; int n, m; ll H ; char str , str2 ; inline ll idx(char c) { return c - 'a' + 1; } inline int get(int pos) { return n - pos + 1; } void init() { H[0] = 1; for(int i = 1; i < N; i++) { H[i] = H[i-1] * sigma_size; } } ll lsum[N<<2], rsum[N<<2]; void pushUp(int o, int L, int R) { int M = (L + R)/2; lsum[o] = H[R - M] * lsum[ls] + lsum[rs]; rsum[o] = H[R - M] * rsum[ls] + rsum[rs]; } void build(int o, int L, int R) { if(L == R) { lsum[o] = idx(str[L]); rsum[o] = idx(str2[L]); return ; } int M = (L + R) >> 1; build(lson); build(rson); pushUp(o, L, R); } void modify(int o, int L, int R, int pos, int op) { if(L == R) { if(op == -1) lsum[o] = idx(str[L]); else rsum[o] = idx(str2[L]); return ; } int M = (L + R) >> 1; if(pos <= M) modify(lson, pos, op); else modify(rson, pos, op); pushUp(o, L, R); } ll query(int o, int L, int R, int ql, int qr, int op) { if(ql <= L && R <= qr) return (op == -1) ? lsum[o] : rsum[o]; int M = (L + R) >> 1; if(qr <= M) return query(lson, ql, qr, op); else if(ql > M) return query(rson, ql, qr, op); return query(lson, ql, M, op) * H[qr - M] + query(rson, M+1, qr, op); } int main() { char oper[20], c[5]; int a, b; init(); while(~scanf("%s", str+1)) { n = strlen(str+1); strcpy(str2+1, str+1); reverse(str2+1, str2+1+n); build(1, 1, n); scanf("%d", &m); ll pre, suf; while(m--) { scanf("%s", oper); if(oper[0] == 'p') { scanf("%d%d", &a, &b); int mid = (a + b) >> 1; int flag = (a + b) & 1; pre = query(1, 1, n, a, mid, -1); suf = query(1, 1, n, get(b), get(mid+flag), 1); puts((pre == suf) ? "Yes" : "No"); }else { scanf("%d%s", &a, c); str[a] = c[0]; modify(1, 1, n, a, -1); str2[get(a)] = c[0]; modify(1, 1, n, get(a), 1); } } } return 0; }
相关文章推荐
- 移动web之响应式布局
- ubuntu 14.04 安装配置使用搜狗拼音输入法
- C语言数组指针指针数组
- VirtualBox更改虚拟机磁盘VDI的大小
- c# 函数
- DOM操作
- 【JS笔记】私有变量
- servlet生命周期详解
- uint16,uint32是什么?
- uint16,uint32是什么?
- fabs(x)函数求绝对值
- 前端中容易犯低级错误的地方
- vim编辑器简单使用(1)
- Merge Intervals
- 从Java文件到字节码文件
- 个人--如何辨别添加了防腐剂的牛奶?
- leetCode #264 Ugly Number II
- 归并排序_分治算法 (白书P226)
- Java创建二叉树
- G. February 29(时间推算问题)