zoukankan      html  css  js  c++  java
  • 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
    ", ++t);
    146         printf("val:%d lson:%d rson:%d lhash:%d rhash:%d
    ", 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
    ", splay.query(a));
    176     }
    177 }
    View Code
  • 相关阅读:
    SpringBoot初识日志
    SpringBoot配置文件(2)
    SpringBoot配置文件(1)
    java8新特性之stream流
    java8新特性之Lambda表达式
    Java入门——第一个Java程序HelloWorld(Dos命令窗口)
    Invalid bound statement (not found): com.xxx.xxx.dao.ShopMapper.insertShop
    2019总结过去,规划未来
    进程和线程的区别
    python(tuple元组、scalar types:数字类型、字符类型、类型转换)
  • 原文地址:https://www.cnblogs.com/oyking/p/3896588.html
Copyright © 2011-2022 走看看