• CF914F Substrings in a String


    一、题目

    点此看题

    二、解法

    首先不难想到对询问的字符串值域分块,也就是对于长度大于 \(\sqrt n\) 的可以暴力建立后缀自动机计算,对于长度小于等于 \(\sqrt n\) 的串用分块维护。

    每个块内维护后缀自动机,修改时暴力重构。对于跨块的字符串,我们可以把两边长度为 \(len-1\) 的后缀和前缀拼起来建立后缀自动机,时间复杂度是 \(O(n\sqrt n)\),但是常数太大了!


    更好的做法是,我们直接用 \(\tt bitset\) 计算哪些位置可以作为开头,具体做法就是维护每个字符出现位置,然后对于询问串的每个字符都相当于并上一个 \(\tt bitset\),那么答案就便于计算了,时间复杂度 \(O(\frac{n^2}{w})\)

    #include <cstdio>
    #include <bitset>
    #include <cstring>
    #include <iostream>
    using namespace std;
    const int M = 100005;
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,m;char s[M],t[M];bitset<M> a[26],ans;
    signed main()
    {
    	scanf("%s",s+1);n=strlen(s+1);
    	for(int i=1;i<=n;i++)
    		a[s[i]-'a'].set(i,1);
    	m=read();
    	while(m--)
    	{
    		int op=read();
    		if(op==1)
    		{
    			int x=read();
    			a[s[x]-'a'].set(x,0);
    			scanf("%c",&s[x]);
    			a[s[x]-'a'].set(x,1);
    		}
    		else
    		{
    			int l=read(),r=read(),len=0;
    			scanf("%s",t+1);len=strlen(t+1);
    			ans.set();
    			for(int i=1;i<=len;i++)
    				ans&=a[t[i]-'a']>>(i-1);
    			int A=(ans>>l).count();
    			A-=(ans>>(r-len+2)).count();
    			printf("%d\n",max(A,0));
    		}
    	}
    }
    
  • 相关阅读:
    简述智障版本搜索引擎架构
    kaggle PredictingRedHatBusinessValue 简单的xgboost的交叉验证
    机器学习速查表
    World final 2017 题解
    微博爬虫
    喵哈哈村的魔法考试 Round #21 (Div.2) 题解
    喵哈哈村的魔法考试 Round #20 (Div.2) 题解
    Tinkoff Challenge
    常用的机器学习&数据挖掘知识(点)总结
    喵哈哈村的魔法考试 Round #19 (Div.2) 题解
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/16258252.html
Copyright © 2020-2023  润新知