CCC比赛T3
参加了CCC
我好菜啊
做对的就几道水题
T3的题目大意是给一个字串,然后再给一个母串,看字串有几种排列方式在母串中出现过
(只包含小写字母)
举个例子
ab的排列在aba中出现过2种
ab和ba
数据范围是10^5(好像
首先是判断排列,按照全排列来判断肯定不行,所以选择使用一个数组,记录每个字母出现的次数
在母串判断的时候滑动一下就可以判断是否是字串的一种排列方式,因为只要每个字母的数量都一样,就说明是一种排列
然后如何避免排列重复呢,直接用一个hash就可以,因为这道题的数据还挺强的,我开了三个hash才过掉(也可能是因为我脸黑
反正这道题是水题,我就不多说了(找机会把后面两道题弄懂
上代码吧:
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<cstdio> #include<cstdlib> #define mod1 12582917 #define mod2 6291469 #define mod3 25165843 #define base 131 #define ULL unsigned long long using namespace std; inline long long rd(){ long long x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x*f; } inline void write(long long x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); return ; } char ch1[1000006],ch2[1000006]; int cnt[1006]; int num[1006]; ULL ha[1000006]; ULL poww[1000006]; int n,m; bool book1[13000006]; bool book2[13000006]; bool book3[30000006]; int ans=0; inline ULL geth(int l,int r){ return ha[r]-(ha[l-1]*poww[r-l+1]); } int main(){ //freopen(".in","r",stdin); //freopen(".out","w",stdout); poww[0]=1; for(int i=1;i<=1000006;i++) poww[i]=(poww[i-1]*base); cin>>ch1+1; cin>>ch2+1; n=strlen(ch1+1); m=strlen(ch2+1); for(int i=1;i<=m;i++){ ha[i]=((ha[i-1]*base)+(ULL)(ch2[i]-'a'+1)); } for(int i=1;i<=n;i++){ cnt[ch1[i]-'a'+1]++; } for(int i=1;i<=n;i++){ num[ch2[i]-'a'+1]++; } for(int i=n;i<=m;i++){ int f=0; for(int j=1;j<=26;j++){ if(cnt[j]!=num[j]){ f=1; break; } } num[ch2[i-n+1]-'a'+1]--; num[ch2[i+1]-'a'+1]++; if(f) continue; ULL v1=geth(i-n+1,i); ULL v2=v1,v3=v1; v1%=mod1; v2%=mod2; v3%=mod3; if(!book1[v1]||!book2[v2]||!book3[v3]){ book1[v1]=book2[v2]=book3[v3]=1; ans++; } } write(ans); return 0; }
蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿