也是之前遗留下来的一道线段树题目…当时query的实现没有思路。今天早上心血来潮就开干了…
说一下线段树的各种构造查找更新吧。
首先是各节点的num值分别储存俩字符串第i位字符是否相等,相等的话为1,否则为0.
上面的节点的num就储存区间内1的值的总和。
更新掠过。
感觉查找是此题重点。
1.查找的时候先寻找以i为起点的左区间。
2.判断此区间是否为满区间都为公共字符串,如果是就加上右区间以左端点为起点的最长公共字符串长度并返回。
3.否则,查找更小的以i为起点的左区间。(重复1,2)
一个小剪枝:一开始查询或查询过程的整个大区间都是公共字符串序列的话,直接输出 该区间右儿子-i+1;
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxx = 1001000;
char s[2][maxx];
struct tre
{
int lson,rson;
int num;
} tree[maxx<<2];
void build(int left, int right, int dex)
{
tree[dex].lson = left;
tree[dex].rson = right;
if(tree[dex].lson == tree[dex].rson) return ;
int mid = (tree[dex].lson+tree[dex].rson)>>1;
build(left,mid,dex<<1);
build(mid+1,right,dex<<1|1);
}
void update(int dir,int dex,int add)
{
tree[dex].num+=add;
int mid = (tree[dex].lson+tree[dex].rson)>>1;
if(tree[dex].lson == tree[dex].rson) return;
if(mid>=dir && tree[dex].lson<=dir) update(dir,dex<<1,add);
if(dir>=mid+1 && dir<=tree[dex].rson) update(dir,dex<<1|1,add);
}
int query(int i, int dex)
{
int mid = (tree[dex].lson + tree[dex].rson)>>1;
if(tree[dex].rson - tree[dex].lson + 1 == tree[dex].num) return tree[dex].rson - i + 1;
if(tree[dex].lson == i)
{
if(tree[dex].rson - tree[dex].lson +1 == tree[dex].num) return tree[dex].num;
else if(tree[dex].num == 0) return 0;
else
{
int tem = query(i,dex<<1);
if(tem==mid - i+1) return tem + query(mid+1,dex<<1|1);
else return tem;
}
}
if(i>mid)
{
return query(i,dex<<1|1);
}
else if(i<=mid)
{
int tem = query(i,dex<<1);
if(tem==mid - i+1) return tem + query(mid+1,dex<<1|1);
else return tem;
}
}
int main()
{
// freopen("1009.txt","r",stdin);
// freopen("1009.in","r",stdin);
// freopen("out.txt","w",stdout);
int t;
scanf("%d",&t);
for(int cases=1; cases<=t; cases++)
{
memset(tree,0,sizeof(tree));
printf("Case %d:\n",cases);
scanf("%s %s",s[0]+1,s[1]+1);
int len = max(strlen(s[0]+1),strlen(s[1]+1));
build(1,len,1);
for(int i=1; i<=len; i++) if(s[0][i]==s[1][i]) update(i,1,1);
int q;
scanf("%d",&q);
while(q--)
{
int a,i,command;
char ch;
scanf("%d",&command);
if(command==1)
{
scanf("%d %d %c",&a,&i,&ch);
a--;
i++;
int b=!a;
if(s[a][i]==s[b][i] && ch!=s[b][i])
{
update(i,1,-1);
s[a][i] = ch;
}
else if(s[a][i]!=s[b][i] && ch==s[b][i])
{
update(i,1,1);
s[a][i] = ch;
}
else s[a][i] = ch;
}
else
{
scanf("%d",&a);
printf("%d\n",query(a+1,1));
}
}
}
return 0;
}