ACdream 1104 瑶瑶想找回文串(SplayTree + Hash + 二分)

Problem Description

刚学完后缀数组求回文串的瑶瑶(tsyao)想到了另一个问题:如果能够对字符串做一些修改,怎么在每次询问时知道以某个字符为中心的最长回文串长度呢?因为瑶瑶整天只知道LOL,当他知道自己省选成绩的时候就天天在LOL,导致现在的她实在是太弱了,根本解决不了这个问题,于是就来找你帮忙,么么哒~你就帮帮她吗

Input

第一行为一个长度不超过100000字符串s作为初始字符串。第二行一个正整数n,表示操作/询问的个数。接下来n行,每行有如下几种可能出现的操作/询问:

Insert a x  在a处字符的后面插入一个字符x

Delete a  把a处字符删除

Update a x 把a处字符改为x

Query a 查询以a为中心的最长回文串长度

Output

对于每个询问,输出得到的最长回文串长度

 

题目大意:略。

思路:

——————————————————————————————————————————————————————————

搬一下官方(?)题解:http://tsyao.tk/archives/94

SPLAY保存改区间从左向右的hash值和从右向左的hash值,对于每个询问,二分字符串长度。总的时间复杂度是O(qlognlogn)

——————————————————————————————————————————————————————————

处理技巧:头尾加上一个空字符可以不用考虑边界的情况。

 

代码(1932MS):

  1 #include <cstdio>

  2 #include <iostream>

  3 #include <cstring>

  4 #include <algorithm>

  5 using namespace std;

  6 typedef long long LL;

  7 

  8 const int MAXN = 150010;

  9 const int MOD = 1e8 + 7;

 10 const LL seed = 131;

 11 

 12 LL base[MAXN];

 13 char s[MAXN], op[10];

 14 int n, m;

 15 

 16 void initBase(int n = 150000) {

 17     base[0] = 1;

 18     for(int i = 1; i <= n; ++i) base[i] = base[i - 1] * seed % MOD;

 19 }

 20 

 21 struct SplayTree {

 22     struct Node {

 23         int size, lhash, rhash;

 24         char c;

 25         Node *fa, *ch[2];

 26     };

 27     Node statePool[MAXN], *nil, *root;

 28     int stk[MAXN], top;

 29     int ncnt;

 30 

 31     SplayTree() {

 32         nil = statePool;

 33     }

 34 

 35     void init() {

 36         ncnt = 1;

 37         top = 0;

 38     }

 39 

 40     Node* new_node(char v, Node* f) {

 41         Node* t;

 42         if(top) t = &statePool[stk[--top]];

 43         else t = &statePool[ncnt++];

 44         t->size = 1;

 45         t->lhash = t->rhash = t->c = v;

 46         t->ch[0] = t->ch[1] = nil;

 47         t->fa = f;

 48         return t;

 49     }

 50 

 51     void del_node(Node* &x) {

 52         stk[top++] = x - statePool;

 53         x = nil;

 54     }

 55 

 56     void update(Node* x) {

 57         int s0 = x->ch[0]->size, s1 = x->ch[1]->size;

 58         x->size = s0 + s1 + 1;

 59         x->lhash = (x->ch[0]->lhash * base[s1 + 1] + x->c * base[s1] + x->ch[1]->lhash) % MOD;

 60         x->rhash = (x->ch[1]->rhash * base[s0 + 1] + x->c * base[s0] + x->ch[0]->rhash) % MOD;

 61     }

 62 

 63     void rotate(Node* x) {

 64         Node* y = x->fa;

 65         int t = (y->ch[1] == x);

 66         y->fa->ch[y->fa->ch[1] == y] = x; x->fa = y->fa;

 67         y->ch[t] = x->ch[t ^ 1]; x->ch[t ^ 1]->fa = y;

 68         x->ch[t ^ 1] = y; y->fa = x;

 69         update(y);

 70     }

 71 

 72     void splay(Node* x, Node* f) {

 73         while(x->fa != f) {

 74             if(x->fa->fa == f) rotate(x);

 75             else {

 76                 Node *y = x->fa, *z = y->fa;

 77                 if((z->ch[1] == y) == (y->ch[1] == x)) rotate(y);

 78                 else rotate(x);

 79                 rotate(x);

 80             }

 81         }

 82         update(x);

 83         if(x->fa == nil) root = x;

 84     }

 85 

 86     Node* kth(int k) {

 87         Node* x = root;

 88         while(true) {

 89             int t = x->ch[0]->size + 1;

 90             if(t == k) break;

 91             if(t > k) x = x->ch[0];

 92             else x = x->ch[1], k -= t;

 93         }

 94         return x;

 95     }

 96 

 97     void build(Node* &x, Node* f, int l, int r) {

 98         int mid = (l + r) >> 1;

 99         x = new_node(s[mid], f);

100         if(l < mid) build(x->ch[0], x, l, mid - 1);

101         if(mid < r) build(x->ch[1], x, mid + 1, r);

102         update(x);

103     }

104 

105     void insert(int pos, char c) {

106         splay(kth(pos), nil);

107         splay(kth(pos + 1), root);

108         root->ch[1]->ch[0] = new_node(c, root->ch[1]);

109         update(root->ch[1]); update(root);

110     }

111 

112     void modify(int pos, char c) {

113         splay(kth(pos), nil);

114         root->c = c;

115         update(root);

116     }

117 

118     void remove(int pos) {

119         splay(kth(pos - 1), nil);

120         splay(kth(pos + 1), root);

121         del_node(root->ch[1]->ch[0]);

122         update(root->ch[1]); update(root);

123     }

124 

125     bool check(int pos, int len) {

126         splay(kth(pos - len - 1), nil);

127         splay(kth(pos + len + 1), root);

128         splay(kth(pos), root->ch[1]);

129         Node* x = root->ch[1]->ch[0];

130         return x->lhash == x->rhash;

131     }

132 

133     int query(int pos) {

134         int l = 1, r = min(pos - 2, root->size - 1 - pos) + 1;

135         while(l < r) {

136             int mid = (l + r) >> 1;

137             if(check(pos, mid)) l = mid + 1;

138             else r = mid;

139         }

140         return 2 * l - 1;

141     }

142 

143     void debug(Node* x) {

144         static int t = 0;

145         if(x == root) printf("Debug %d\n", ++t);

146         printf("val:%d lson:%d rson:%d lhash:%d rhash:%d\n", x - statePool, x->ch[0] - statePool, x->ch[1] - statePool, x->lhash, x->rhash);

147         if(x->ch[0] != nil) debug(x->ch[0]);

148         if(x->ch[1] != nil) debug(x->ch[1]);

149     }

150 } splay;

151 

152 int main() {

153     scanf("%s", s + 1);

154     n = strlen(s + 1);

155     initBase();

156     splay.init();

157     splay.build(splay.root, splay.nil, 0, n + 1);

158     scanf("%d", &m);

159     char c;

160     for(int i = 0, a; i < m; ++i) {

161         scanf("%s%d", op, &a);

162         ++a;

163         if(strcmp(op, "Insert") == 0) {

164             scanf(" %c", &c);

165             splay.insert(a, c);

166         }

167         if(strcmp(op, "Delete") == 0)

168             splay.remove(a);

169         if(strcmp(op, "Update") == 0) {

170             scanf(" %c", &c);

171             splay.modify(a, c);

172         }

173         //splay.debug(splay.root);

174         if(strcmp(op, "Query") == 0)

175             printf("%d\n", splay.query(a));

176     }

177 }
View Code

 

你可能感兴趣的:(tree)