题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4339
题目意思:
给两个字符串,有两种操作。
1、改变一字符串的某个位置的一个字符。
2、查找某一位置开始的最大的连续的两串相同的字符的个数。
解题思路:
线段树维护两个值:该区间最左边连续的最大值,最右边连续的最大值。
每做一道题,停下思考,抽象出一点体会。
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x1f1f1f1f
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define Maxn 1100000
/*
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
*/
struct Node
{
int ls,rs;
}node[Maxn*4]; //线段树维护区间两个值,1、包括左端点位置的最大连续相等的个数,
//2、包括右端点位置的最大连续相等的个数
char sa1[Maxn],sa2[Maxn];
int nm,n;
void pushup(int rt,int num) //向上更新
{
node[rt].ls=node[rt<<1].ls;
node[rt].rs=node[rt<<1|1].rs;
if(node[rt].ls>=num-(num>>1)) //左孩子区间个数为num-(num>>1)
node[rt].ls+=node[rt<<1|1].ls;
if(node[rt].rs>=(num>>1)) //右孩子区间个数为num>>1
node[rt].rs+=node[rt<<1].rs;
}
void build(int l,int r,int rt)
{
if(l==r)
{
if(l<nm) //两串的最小长度
node[rt].ls=node[rt].rs=(sa1[l]==sa2[r])?1:0;
else
node[rt].ls=node[rt].rs=0;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt,r-l+1);
}
void update(int k,int l,int r,int rt)
{
if(l==r)
{
if(l<nm)
node[rt].ls=node[rt].rs=(sa1[l]==sa2[r])?1:0;
else
node[rt].ls=node[rt].rs=0;
return ;
}
int m=(l+r)>>1;
if(k<=m)
update(k,lson);
else
update(k,rson);
pushup(rt,r-l+1);
}
int query(int k,int l,int r,int rt)
{
if(l==r)
return 1; //该位置一定是相同的
int m=(l+r)>>1;
if(k<=m)
{
if(node[rt<<1].rs>m-k) //只用从该位置向右考虑就行了
return m-k+1+node[rt<<1|1].ls;
else
return query(k,lson);
}
else
return query(k,rson);
}
int main()
{
// scanf("%s",sa1);
// scanf("%s",sa1);
// printf("%c\n",sa1[5]);
int t;
int ab,po,m,ki;
char s[5];
scanf("%d",&t);
for(int ca=1;ca<=t;ca++)
{
scanf("%s",sa1);
scanf("%s",sa2);
int len1=strlen(sa1),len2=strlen(sa2);
n=max(len1,len2);
nm=min(len1,len2);
build(0,n-1,1);
printf("Case %d:\n",ca);
scanf("%d",&m);
while(m--)
{
scanf("%d",&ki);
if(ki==1)
{
scanf("%d%d%s",&ab,&po,s);
if(ab==1)
sa1[po]=*s;
else
sa2[po]=*s;
update(po,0,n-1,1);
}
else
{
scanf("%d",&po);
if(po>=nm||sa1[po]!=sa2[po])
{
printf("0\n");
continue;
}
printf("%d\n",query(po,0,n-1,1));
}
}
}
return 0;
}