题目大意:初始给出一个字符串,下面有一些操作,可以在一个地方加一个字符,询问从两个地方开始最长的匹配长度。
思路:Splay维护Hash值,询问的时候二分一下就行了。它条件给的比较恶心,注意处理的时候按照他说的做就行了。
CODE:
#define _CRT_SECURE_NO_DEPRECATE #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 51010 #define BASE 2333 using namespace std; #define WORKPATH (root->son[1]->son[0]) unsigned long long power[MAX]; struct SplayTree{ int val,size; unsigned long long hash; SplayTree *son[2],*father; SplayTree(int _); SplayTree() {} void Combine(SplayTree *a,bool dir) { son[dir] = a; a->father = this; } bool Check() { return father->son[1] == this; } void PushUp() { size = son[0]->size + son[1]->size + 1; hash = son[0]->hash + val * power[son[0]->size] + son[1]->hash * power[son[0]->size + 1]; } }*root,none,*nil = &none,*src[MAX]; SplayTree :: SplayTree(int _) { val = hash = _; size = 1; son[0] = son[1] = nil; } void Pretreatment() { power[0] = 1; for(int i = 1; i < MAX; ++i) power[i] = power[i - 1] * BASE; nil->son[0] = nil->son[1] = nil->father = nil; } char s[MAX]; SplayTree *BuildTree(int l,int r) { if(l > r) return nil; int mid = (l + r) >> 1; SplayTree *re = new SplayTree(s[mid]); src[mid] = re; re->Combine(BuildTree(l,mid - 1),false); re->Combine(BuildTree(mid + 1,r),true); re->PushUp(); return re; } inline void Rotate(SplayTree *a,bool dir) { SplayTree *f = a->father; f->son[!dir] = a->son[dir]; f->son[!dir]->father = f; a->son[dir] = f; a->father = f->father; f->father->son[f->Check()] = a; f->father = a; f->PushUp(); if(root == f) root = a; } inline void Splay(SplayTree *a,SplayTree *aim) { while(a->father != aim) { if(a->father->father == aim) Rotate(a,!a->Check()); else if(!a->father->Check()) { if(!a->Check()) Rotate(a->father,true),Rotate(a,true); else Rotate(a,false),Rotate(a,true); } else { if(a->Check()) Rotate(a->father,false),Rotate(a,false); else Rotate(a,true),Rotate(a,false); } } a->PushUp(); } SplayTree *Find(SplayTree *a,int k) { if(a->son[0]->size >= k) return Find(a->son[0],k); k -= a->son[0]->size; if(k == 1) return a; return Find(a->son[1],k - 1); } int asks; int length; inline unsigned long long GetHash(int l,int len) { int l_size; Splay(src[l],nil),l_size = root->son[0]->size + 1; if(l_size + len > length + 2) throw false; Splay(Find(root,l_size - 1),nil); Splay(Find(root,l_size + len),root); return WORKPATH->hash; } inline bool Judge(int x,int y,int ans) { unsigned long long l,r; try{ l = GetHash(x,ans); r = GetHash(y,ans); } catch(bool) { return false; } return l == r; } int main() { Pretreatment(); scanf("%s",s + 1); length = strlen(s + 1); root = BuildTree(0,length + 1); root->father = nil; cin >> asks; for(int x,y,i = 1; i <= asks; ++i) { scanf("%s",s); if(s[0] == 'Q') { scanf("%d%d",&x,&y); int l = 0,r = length,ans = 0; while(l <= r) { int mid = (l + r) >> 1; if(Judge(x,y,mid)) l = mid + 1,ans = mid; else r = mid - 1; } printf("%d\n",ans); } else { scanf("%s%d",s,&x); if(x > length) x = length + 1; ++length; Splay(Find(root,x),nil); Splay(Find(root,x + 1),root); root->son[1]->Combine(new SplayTree(s[0]),false); root->son[1]->PushUp(); root->PushUp(); } } return 0; }
BZOJ 2258 pku2758 Checking the Text 文本校对 Splay+Hash+二分
原文地址:http://blog.csdn.net/jiangyuze831/article/details/42968315