这道题的话……首先得知道怎么求(LCP)。我们的方法首先二分一个长度,之后判断一下该区间内两段字符串的(hash)值是否相等,这样就可以啦。
然后本题还要求支持插入和修改字母,所以我们需要使用一棵(splay)来维护(hash)值。具体做法是动态维护每一个节点的子树的(hash)值,在合并的时候,有(hash[x] = hash[l] imes base^{size[r]+1} + (s[x] - 'a') imes base^{size[r]} + hash[r]),这样修改就可以了。
然后本题的建树可以直接建成完美的(splay),之后插入的时候先把要插入的位置(splay)出来之后插到右子树上。计算(hash)值的时候就(splay)一段区间出来取(hash)值就可以了。
做这道题的时候发现了长久以来的问题……更新的时候要先更新儿子后更新父亲……以前模板题怎么写都能过,但是这题先更新父亲会RE……debug了好久。注意在头尾各插入了一个无用字符,以防止出错。
看一下代码。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('
')
#define de putchar('#')
#define pr pair<int,int>
#define mp make_pair
#define fi first
#define sc second
#define B puts("GG")
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int M = 200005;
const int N = 10000005;
const int INF = 1000000009;
const ull base = 47;
int read()
{
int ans = 0,op = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-') op = -1;
ch = getchar();
}
while(ch >='0' && ch <= '9')
{
ans *= 10;
ans += ch - '0';
ch = getchar();
}
return ans * op;
}
struct node
{
int fa,ch[2],size;
ull hash,val;
char c;
}t[M<<1];
int n,m,x,y,root,idx,cnt;
ull po[M];
char s[M],a[5];
bool get(int x)
{
return t[t[x].fa].ch[1] == x;
}
void update(int x)
{
int lson = t[x].ch[0],rson = t[x].ch[1];
t[x].hash = t[lson].hash * po[t[rson].size+1] + t[x].val * po[t[rson].size] + t[rson].hash;
t[x].size = t[lson].size + t[rson].size + 1;
}
void rotate(int x)
{
int y = t[x].fa,z = t[y].fa,k = get(x);
t[z].ch[get(y)] = x,t[x].fa = z;
t[y].ch[k] = t[x].ch[k^1],t[t[y].ch[k]].fa = y;
t[x].ch[k^1] = y,t[y].fa = x;
update(y),update(x);
}
void splay(int x,int goal)
{
while(t[x].fa != goal)
{
int y = t[x].fa,z = t[y].fa;
if(z != goal) (t[y].ch[0] == x) ^ (t[z].ch[0] == y) ? rotate(x) : rotate(y);
rotate(x);
}
if(!goal) root = x;
}
int build(int f,int l,int r)
{
if(l > r) return 0;
int mid = (l+r) >> 1,u = ++cnt;
t[u].val = s[mid] - 'a' + 1,t[u].fa = f,t[u].c = s[mid];
t[u].ch[0] = build(u,l,mid-1),t[u].ch[1] = build(u,mid+1,r);
update(u);
return u;
}
int find(int x)
{
int u = root;
while(1)
{
if(x <= t[t[u].ch[0]].size) u = t[u].ch[0];
else if(x == t[t[u].ch[0]].size+1) return u;
else x -= (t[t[u].ch[0]].size + 1),u = t[u].ch[1];
}
}
void modify(int x)
{
int g = find(x);
splay(g,0),t[g].val = a[0] - 'a' + 1,t[g].c = a[0],update(g);
}
void insert(int x)
{
int g = find(x),h = find(x+1);
splay(g,0),splay(h,g);
int u = ++idx;
t[h].ch[0] = u,t[u].size = 1,t[u].val = t[u].hash = a[0] - 'a' + 1,t[u].fa = h;
t[u].ch[0] = t[u].ch[1] = 0;
update(h),update(g);
}
bool judge(int x,int y,int k)
{
if(k == 0) return 1;
int g = find(x-1),h = find(x+k);
splay(g,0),splay(h,g);
ull cur = t[t[h].ch[0]].hash;
g = find(y-1),h = find(y+k);
splay(g,0),splay(h,g);
ull now = t[t[h].ch[0]].hash;
return cur == now;
}
int query(int x,int y)
{
int L = 0,R = idx,ans = 0;
while(L <= R)
{
int mid = (L + R) >> 1;
if(x + mid > idx || y + mid > idx) {R = mid - 1;continue;}
if(judge(x,y,mid)) ans = mid,L = mid + 1;
else R = mid - 1;
}
return ans;
}
int main()
{
po[0] = 1;rep(i,1,M-2) po[i] = po[i-1] * base;
scanf("%s",s+2),idx = strlen(s+2) + 2;
s[1] = s[idx] = 'f',root = build(0,1,idx);
m = read();
rep(i,1,m)
{
scanf("%s",a),x = read() + 1;
if(a[0] == 'Q') y = read() + 1,printf("%d
",query(x,y));
if(a[0] == 'R') scanf("%s",a),modify(x);
if(a[0] == 'I') scanf("%s",a),insert(x);
}
return 0;
}
*/