zoukankan      html  css  js  c++  java
  • 【YbtOJ#20072】相似子串

    题目

    题目链接:http://noip.ybtoj.com.cn/problem/20072

    思路

    对于一个长度为 (m) 的询问串,显然要求的就是 (s) 中有多少个长度为 (m) 的区间和等于询问串的和。
    考虑根号分治。假设所有询问串串长和为 (t)

    • (mleq sqrt{t}) 时,我们可以预处理 (cnt[i][j]) 表示 (s) 长度为 (i) 的区间有多少个和为 (j)。然后每次可以 (O(1)) 回答。
    • (m>sqrt{t}) 时,显然这种询问次数不会超过 (frac{t}{sqrt t}=sqrt{t}) 次,所以我们每次 (O(n)) 暴力做即可。

    时间复杂度 (O((n+m)sqrt{t}))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=200010,M=450;
    int Q,T,m,n,ans,sum,num,cnt[M][M];
    char s[N],t[N];
    
    int main()
    {
    	freopen("similar.in","r",stdin);
    	freopen("similar.out","w",stdout);
    	scanf("%s",s+1);
    	n=strlen(s+1); T=sqrt(n);
    	s[0]=48;
    	for (int i=1;i<=T;i++)
    	{
    		sum=0;
    		for (int j=1;j<i;j++) sum+=s[j]-48;
    		for (int j=i;j<=n;j++)
    		{
    			sum=sum+(s[j]-48)-(s[j-i]-48);
    			cnt[i][sum]++;
    		}
    	}
    	scanf("%d",&Q);
    	while (Q--)
    	{
    		scanf("%s",t+1);
    		m=strlen(t+1); num=sum=0;
    		for (int i=1;i<=m;i++) num+=t[i]-48;
    		if (m<=T) printf("%d
    ",cnt[m][num]);
    		else
    		{
    			ans=0;
    			for (int i=1;i<m;i++) sum+=s[i]-48;
    			for (int i=m;i<=n;i++)
    			{
    				sum=sum+(s[i]-48)-(s[i-m]-48);
    				if (sum==num) ans++;
    			}
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    ABAP Code Inspector那些隐藏的功能,您都知道吗?
    L2-017. 人以群分
    L2-007. 家庭房产
    L2-014. 列车调度
    L2-004. 这是二叉搜索树吗?
    过山车
    hdu 3746 Cyclic Nacklace
    hdu 1867 A + B for you again
    hdu 1686 Oulipo
    Orders
  • 原文地址:https://www.cnblogs.com/stoorz/p/13879716.html
Copyright © 2011-2022 走看看