首页 > 其他分享 >【求助+半题解】BZOJ1461字符串的匹配

【求助+半题解】BZOJ1461字符串的匹配

时间:2023-07-21 09:15:37浏览次数:43  
标签:前缀 BZOJ1461 int 题解 void 求助 next maxn

先说思路:
因为我们是比对较短的\(B\)与较长的\(A\)的子串,所以我们求不变的\(B\)的\(next\)

对于这道题我们可以使用树状数组查询前缀和维护数的排名。

对于相同的数我们查询的排名是有误的,因此不仅要比对小于等于该数的前缀和,也要比对小于该数的前缀和。

如:对于\(A=2\) \(2\),\(B=1\) \(2\),来说,\(A\)的第二个\(2\)排名应为\(1\),但是前缀和是\(2\)。

对于代码有一求助问题。

点击查看代码
#include<bits/stdc++.h>
using namespace std;

const int maxn=5e6+50;

int n,k,s,next_[maxn];
int A[maxn],B[maxn],c[maxn];
int ranq[maxn],ress[maxn];
int ans,anss[maxn]; 

int lowbit(int x){
	return x&(-x);
}

void update(int x,int y){
	while(x<=s){
		c[x]+=y;
		x+=lowbit(x);
	}
}

int query(int x){
	int ans2=0;
	while(x){
		ans2+=c[x];
		x-=lowbit(x);
	}
	return ans2;
}

inline void input(){
	scanf("%d %d %d",&n,&k,&s);
	for(int i=1;i<=n;++i){
		scanf("%d",&A[i]);
	}
	for(int i=1;i<=k;++i){
		scanf("%d",&B[i]);
		update(B[i],1);
		ranq[i]=query(B[i]);
		ress[i]=query(B[i]-1);
		//cout<<"%%%"<<i<<' '<<ranq[i]<<' '<<ress[i]<<endl;
	}
}

inline void Next(){
	for(int i=2,j=0;i<=k;++i){
		while(j && (query(B[i])!=ranq[j+1] || query(B[i]-1)!=ress[j+1])){
			j=next_[j];
		}
		++j;
		next_[i]=j;
	}
}

inline void match(){
	for(int i=1,j=0;i<=n;++i){
		update(A[i],1);
		while(j &&(query(A[i])!=ranq[j+1] || query(A[i]-1)!=ress[j+1])){
			//cout<<i<<' '<<j+1<<' '<<A[i]<<' '<<query(A[i])<<' '<<ranq[j+1]<<' '<<query(A[i]-1)<<' '<<ress[j+1]<<endl;
			for(int q=i-j;q<i-next_[j];++q){
				update(A[q],-1);
				//比对相同区间把前面的删去
			}
			//cout<<"$$$"<<j<<' '<<next_[j]<<endl;
			j=next_[j];
		}
		//cout<<"###"<<i<<' '<<j<<endl;
		j++;
		if(j==k)	anss[++ans]=i-j+1;
	}
}

int main(){
	input();
	Next();
	memset(c,0,sizeof(c));
	match();
	printf("%d\n",ans);
	for(int i=1;i<=ans;++i){
		printf("%d\n",anss[i]);
	} 
	return 0;
}


我们可以看到\(next\)我写的是:

inline void Next(){
	for(int i=2,j=0;i<=k;++i){
		while(j && (query(B[i])!=ranq[j+1] || query(B[i]-1)!=ress[j+1])){
			j=next_[j];
		}
		++j;
		next_[i]=j;
	}
}

前面也没有清空树状数组。

但是网上的很多题解都写的是:

void get_next(){
    memset(BIT, 0, sizeof(BIT));
    next[1] = 0;
    int i = 2, j = 0, k;
    for (; i <= m; ++i){
        add(b[i], 1);
        while (j && (query(b[i] - 1) != les[j + 1] || query(b[i]) != equ[j + 1])){
            for (k = i - j; k < i - next[j]; ++k)
                add(b[k], -1);
            j = next[j];
        }
        next[i] = ++j;
    }
}

题解来源

我与mp讨论后认为,不清空才是正确的,因为求\(next\)的过程中我们没有将第一个数字放入树状数组,对前缀和一定是有影响的,但是事实上,两种写法都AC了这道题目。

求解答。

标签:前缀,BZOJ1461,int,题解,void,求助,next,maxn
From: https://www.cnblogs.com/sonnety-v0cali0d-kksk/p/17570321.html

相关文章

  • claude初步体验1(含个人遇到各种注册问题解决)
    很久之前体验的了,当记录一下吧(于三月)https://www.anthropic.com/claude-in-slack 若出现下面这个,而且你用了魔法还不行,大概率是你之前登录别的工作区,然后被检测出来不在他支持的地区了,然后官方把你禁用了,禁止你IP访问(我之前就是这样子),就是你的源IP,用魔法也不行。解决方法,重启......
  • LG4868 Preprefix sum 题解
    壹、题目大意给出长度为\(n\)的序列\(a_1\sima_n\),设\(S_i=\sum\limits_{j=1}^ia_j\),有两种操作可以给定\(i\)和\(x\),使得\(a_i=x\),也可以给定\(i\),查询\(\sum\limits_{j=1}^iS_j\)的值\(n\le100000\)贰、思路这道题查询的是\(S\),但实际上是\(a\),而操......
  • 题解 POJ3318【Matrix Multiplication】
    postedon2022-10-2119:56:08|under题解|sourceproblem判断三个\(n\timesn\)的矩阵是否满足\(A\timesB=C\),\(n\leq500\)。solution随机一个行向量\(v\)。若\(a\timesb=c\),则有\(v\timesa\timesb=v\timesc\)(不充分)。显然相乘复杂度仅为\(O(n^2)\)。类似于......
  • 题解 P4955 【[USACO14JAN]Cross Country Skiing S】
    postedon2021-02-2710:04:32|under题解|source这道题其实没有绿这么难,只需要二分+搜索就行了。读入。注意尽量不要用scanf读入bool,这好像是UB,可以用一个变量\(x\)存输入的数,然后直接类型转换。二分。套模版就行了,等一下我们再写\(\operatorname{check}()\)函......
  • CF1152F2 Neko Rules the Catniverse (Large Version) 题解
    发现挨位考虑填哪个不太现实,考虑值域。令\(dp_{i,j,st}\)表示考虑到\(i\),此时序列长度为\(j\),\(i-m\)到\(i-1\)填空状态为\(st\)的方案数,考虑选/不选数即可:\(dp_{i,j,st}\times(\text{popcount}(st)+1)\todp_{i+1,j+1,(2st+1)\&2^m},dp_{i+1,j,(2st)\&2^m}\)乘上那......
  • 题解 //「BZOJ2406」矩阵
    赛时公告现在呢?:现在有弹窗了吗「2023-07-1916:45:07」此时无声胜有声。F.「BZOJ2406」矩阵http://222.180.160.110:1024/contest/3825/problem/7这是头一次见识到把矩阵和网络流结合在一起的题目。不过这种处理方式也是我们在学习二分图时的常客了:把行和列连边表示某一元......
  • 【题解】Luogu[P3360] 偷天换日
    solution开题显然是个树形dp,只不过在树形dp上又增加了背包问题。我们不妨将每个走廊看成一个点,把交叉口看成边(当然也可以把交叉口看成点,不过写起来麻烦一些),于是就转化为了一棵二叉树。我们设\(f_{i,j}\)表示以\(i\)为根的子树内,花费了不超过\(j\)时间,能拿到的最大价值......
  • Frog 3 题解
    Frog3题目大意题意都这么明确了还要这个干什么。存在\(n\)个点,每个点有一个属性\(h_i\),\(h_i\)单增,从点\(i\)移动到点\(j(j>i)\)的代价是\((h_i-h_j)^2+C\),其中\(C\)是给定的常数,求从点\(1\)移动到点\(n\)的最小代价。思路分析斜率优化DP板题。设\(f_i\)......
  • SP10582 题解
    题目链接题意简述给定一个有\(n\)个数的数组,求从第一个数字开始,向后每\(k\)个数字的最大值。题目分析看到没有人用ST表做那我就来发一个吧。这道题可以用ST表做。它可以在经过\(O(N\logN)\)的预处理后,以\(O(1)\)的时间在线回答下标在\(l\)到\(r\)之间的数......
  • 【题解】Luogu[P2607] [ZJOI2008] 骑士
    题目说给定\(n\)个点\(n\)个关系,也就是\(n\)条边,显然是基环树,又因为没有规定一定连通,于是我们可以将题目简化为给定一个基环树森林,点有点权,相邻的两个点不能同时选,问最大点权和。part1我们先考虑如果没有环,只是树,该怎么做。这一部分很简单,令\(f_{i,0/1}\)表示以\(i\)......