Gym

题意:给定字符串char[],以及Q个操作,操作有三种:

    1:pos,chr:把pos位置的字符改为chr

    2:pos:问以pos为中心的回文串长度为多长。

    3:pos:问以pos,pos+1为中心的回文串长度为多长。

思路:用hash表示一段字符串或者连续子串。我们用BIT记录hash前缀和,那么也可以用BIT修改前缀和。然后blabla,乱搞就行了。

当然为了保险,最好用双hash。

(此题暴力也可以过!

暴力代码:3962ms

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=100010;
char c[maxn],t;
int main()
{
    int N,Q,opt,x;
    scanf("%s%d",c+1,&Q); N=strlen(c+1);
    while(Q--){
        scanf("%d%d",&opt,&x);
        if(opt==1){
            scanf(" %c",&t); c[x]=t;
        }
        else if(opt==2){
            int i=x,j=x;
            while(i-1>=1&&j+1<=N&&c[i-1]==c[j+1]) i--,j++;
            printf("%d
",j-i+1);
        }
        else {
            if(c[x]!=c[x+1]) { puts("-1"); continue;}
            int i=x,j=x+1;
            while(i-1>=1&&j+1<=N&&c[i-1]==c[j+1]) i--,j++;
            printf("%d
",j-i+1);
        }
    }
    return 0;
}
View Code

hash+BIT+二分:93ms(目前排第一?

#include<bits/stdc++.h>
#define uint unsigned int
using namespace std;
const int maxn=100010;
const uint seed=131;
char c[maxn]; uint sum[maxn][2],p[maxn]; int N;
uint query(int x,int opt){
    uint res=0; while(x) {
        res+=sum[x][opt]; x-=(-x)&x;
    } return res;
}
bool check(int L,int R)
{
    if(L<1||R>N) return false;
    uint h1=(query(R,0)-query(L-1,0))*p[L-1];
    uint h2=(query(R,1)-query(L-1,1))*p[N-R];
    if(h1==h2) return true; return false;
}
int main()
{
    int Q,i,j;
    scanf("%s%d",c+1,&Q); N=strlen(c+1);
    p[0]=1; 
    for(i=1;i<=N;i++) p[i]=p[i-1]*seed;
    for(i=1;i<=N;i++){
        for(j=i;j<=N;j+=(-j)&j) sum[j][0]+=p[N-i]*c[i];
        for(j=i;j<=N;j+=(-j)&j) sum[j][1]+=p[i-1]*c[i];
    }
    int opt,x,L,R,Mid,ans; char chr;
    while(Q--){
        scanf("%d%d",&opt,&x);
        if(opt==1){
            scanf(" %c",&chr);
            for(j=x;j<=N;j+=(-j)&j) sum[j][0]+=p[N-x]*(chr-c[x]);
            for(j=x;j<=N;j+=(-j)&j) sum[j][1]+=p[x-1]*(chr-c[x]);
            c[x]=chr;
        }
        else if(opt==2){
            L=0; R=N; ans=1;
            while(L<=R){
                Mid=(L+R)>>1;
                if(check(x-Mid,x+Mid)) ans=Mid,L=Mid+1;
                else R=Mid-1;
            }
            printf("%d
",ans*2+1);
        }
        else{
            L=0; R=N; ans=-1;
            while(L<=R){
                Mid=(L+R)>>1;
                if(check(x-Mid,x+1+Mid)) ans=Mid,L=Mid+1;
                else R=Mid-1;
            }
            printf("%d
",ans==-1?-1:ans*2+2);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/hua-dong/p/9508189.html