2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 G题 Query on a string

题意:

给出字符串S和字符串T

然后q次查询

查询分为两种:

1:查询字符串区间[x,y]内T能被匹配几次

2.修改字符串S[x]为c


题解:

树状数组+瞎搞

用树状数组保存前k个位置能匹配几次T

第i个位置能匹配的意思是 S[i~i+len-1] = T[1~len]  len是字符串T的长度


首先预处理出树状数组,然后查询时直接给出答案,修改时先将字符串修改,再将树状数组修改,因为T的长度最大为10所以可以直接暴力处理



code:

#include<iostream>
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
ll mod = 1e9+7;
const ll INF = 1e18;
typedef pair<int, int>P;
const double eps = 1e-6;
const int maxn = 1e5+5;
template <class T>
inline bool scan_d(T &ret)
{
    char c;
    int sgn;
    if(c=getchar(),c==EOF) return 0; //EOF
    while(c!='-'&&(c<'0'||c>'9')) c=getchar();
    sgn=(c=='-')?-1:1;
    ret=(c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    ret*=sgn;
    return 1;
}
inline void out(ll x)
{
    if(x>9) out(x/10);
    putchar(x%10+'0');
}

int lowbit(int p)
{
    return (p&(-p));
}
int n;
int c[maxn];
void add(int p,int num)
{
    while (p<=n)
    {
        c[p]+=num;
        p+=lowbit(p);//向上修改
    }
    return;
}
int query(int p)
{
    int tmp=0;
    while (p)
    {
        tmp+=c[p];
        p-=lowbit(p);//向前询问
    }
    return tmp;
}
char s[maxn];
char t[15];
bool vis[maxn];
int main()
{
    int T;
    cin >> T;
    while(T--) {
        int q;
        scanf("%d", &q);
        scanf("%s", s+1);
        scanf("%s", t+1);
        int lens = strlen(s+1);
        int lent = strlen(t+1);
        n = lens;
        memset(vis, false, sizeof(vis));
        memset(c, 0, sizeof(c));
        for(int i=1; i+lent-1<=lens; i++) {
            bool f = true;
            for(int j=1; j<=lent; j++) {
                if(s[i+j-1]!=t[j]) {
                    f = false;
                    break;
                }
            }
            if(f) {
                add(i, 1);
                vis[i] = true;
            }
        }
        while(q--) {
            char c;
            scanf("\n%c", &c);
            if(c=='Q') {
                int x, y;
                scanf("%d%d", &x, &y);
                y -= lent;
                y++;
                if(x <= y)
                    printf("%d\n", query(y)-query(x-1));
                else
                    puts("0");
            }
            else {
                int x;
                char y;
                scanf("%d %c", &x, &y);
                s[x] = y;
                for(int i=max(1, x-lent+1); i<=min(lens-lent+1, x); i++) {
                    int f = 1;
                    for(int j=1; j<=lent; j++) {
                        if(s[i+j-1]!=t[j]) {
                            f = 0;
                            break;
                        }
                    }
                    if(f != vis[i]) {
                        if(vis[i])
                            add(i, -1);
                        else
                            add(i, 1);
                        vis[i] = !vis[i];
                    }
                }
            }
        }
        puts("");
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值