7题弟弟。
提交次数最多的两题是C和G,这里决定写一下。
G:
一眼题,题目即是问,给定字符串T,有多少S的子区间s,满足s和T的首尾相同,中间的那些字母每一种的个数相同。不难想到hash。
因为时限比较长,所以可以暴力一点的,把询问长度相同的拿出来一块处理。 这样的不同种类<sqrt种。 所以总的复杂度就是O(NsqrtN*k)。k是hash的复杂度,我开始用unorderedmap存的,T了,然后改成二分才过了。
可以参考CF963D的hash做法。 吃饭了先
#include<bits/stdc++.h> #define ll unsigned long long #define pui pair<ll,int> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=100010; const int seed=131; char a[maxn],b[maxn]; vector<pui>s[maxn]; ll p[150]; int ans[maxn]; ll h[maxn],cnt; int L[maxn],tot,M,N; inline void read(int &x){ x=0; char c=getchar(); while(c>‘9‘||c<‘0‘) c=getchar(); while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar(); } inline void P(int x) { if(x>9) P(x/10); putchar(x%10+‘0‘); } inline void Get() { M=1; b[M]=getchar(); while(b[M]>‘z‘||b[M]<‘a‘) b[M]=getchar(); while(b[M]>=‘a‘&&b[M]<=‘z‘) b[++M]=getchar(); M--; } inline void GetA() { N=1; a[N]=getchar(); while(a[N]>‘z‘||a[N]<‘a‘) a[N]=getchar(); while(a[N]>=‘a‘&&a[N]<=‘z‘) a[++N]=getchar(); N--; } int main() { int T,Q; read(T); p[0]=1; rep(i,1,149) p[i]=p[i-1]*seed; while(T--){ GetA(); read(Q); tot=0; rep(i,1,Q){ Get(); ll now=0; L[++tot]=M; rep(j,2,M-1) { now+=p[b[j]]; } now+=p[123]*b[1]; now+=p[124]*b[M]; s[M].push_back(pui(now,i)); } sort(L+1,L+tot+1); tot=unique(L+1,L+tot+1)-(L+1); rep(k,1,tot){ int i=L[k]; ll now=0,tmp; cnt=0; rep(j,1,N){ if(j>1) now+=p[a[j-1]]; if(j>=i){ now-=p[a[j-i+1]]; tmp=(now+p[123]*a[j-i+1]+p[124]*a[j]); h[++cnt]=tmp; } } sort(h+1,h+cnt+1); rep(j,0,s[i].size()-1) { int p1=upper_bound(h+1,h+cnt+1,s[i][j].first)-h; int p2=lower_bound(h+1,h+cnt+1,s[i][j].first)-h; ans[s[i][j].second]=p1-p2; } s[i].clear(); } rep(i,1,Q) { P(ans[i]); putchar(‘\n‘); } } return 0; }
原文地址:https://www.cnblogs.com/hua-dong/p/11523646.html
时间: 2024-10-12 15:31:23