HDU 4339 Query

题意: 有两个字符串,给出 Q 个询问,每个询问有两种方式:

         1 p i c 把第 p 个字符串的第i 个字符换成 字符 c,

         2 i      从位置i 开始,两个字符串连续相同的子串的最大长度为多少。

分析: 线段树。

          数组len[rt] 保存rt 区间从最左端开始的最长子串,

         合并时,如果len[rt<<1]==mid-l+1  则 len[rt]=len[rt<<1]+len[rt<<1|1]  ,说明可以把右儿子区间直接接到左儿子区间上,否则由于左儿子区间与右儿子区间断开,

         len[rt]=len[rt<<1].

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int maxn=1000005;
char s1[maxn];
char s2[maxn];
int len[maxn<<3];
void creat(int l,int r,int rt)
{
    if(l==r)
    {
        len[rt]=(s1[l]==s2[l]);
        return;
    }
    int m=(l+r)>>1;
    creat(l,m,rt<<1);
    creat(m+1,r,rt<<1|1);
    len[rt]=len[rt<<1];
    if(len[rt<<1]==m-l+1)
        len[rt]+=len[rt<<1|1];
}
void update(int l,int r,int rt,int i,int x)
{
    if(l==r)
    {
        len[rt]=x;
        return;
    }
    int m=(l+r)>>1;
    if(i<=m)
        update(l,m,rt<<1,i,x);
    else update(m+1,r,rt<<1|1,i,x);
    len[rt]=len[rt<<1];
    if(len[rt<<1]==m-l+1)
        len[rt]+=len[rt<<1|1];
}
int query(int l,int r,int rt,int i)
{
    int res=0;
    if(l==i)
        return len[rt];
    int m=(l+r)>>1;
    if(i<=m)
    {
        res+=query(l,m,rt<<1,i);
        if(res==m-i+1)
            res+=len[rt<<1|1];
    }
    else 
        res+=query(m+1,r,rt<<1|1,i);
    return res;
}
int main()
{
    int l1,l2,p,l,t,n,ca=1,k,c,flag;
    char s[2];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s%s",s1+1,s2+1);
        l1=strlen(s1+1);
        l2=strlen(s2+1);
        l=l1<l2?l1:l2;
        creat(1,l,1);
        printf("Case %d:\n",ca++);
        scanf("%d",&n);
        while(n--)
        {
            scanf("%d",&p);
            if(p==1)
            {
                scanf("%d%d%s",&c,&k,s);
                if(k>=l)
                    continue;
                flag=0;
                if(s1[k+1]==s2[k+1])
                    flag=1;
                if(c==1)
                     s1[k+1]=s[0];
                else s2[k+1]=s[0];
                if(s1[k+1]==s2[k+1]&&flag==0)
                    update(1,l,1,k+1,1);
                else if(s1[k+1]!=s2[k+1]&&flag==1)
                    update(1,l,1,k+1,0);
            }
            else 
            {
                scanf("%d",&k);
                if(k>=l)
                    printf("0\n");
                else
                    printf("%d\n",query(1,l,1,k+1));
            }
        }
    }
    return 0;
}

 

posted @ 2012-08-03 21:48  'wind  阅读(187)  评论(0编辑  收藏  举报