别人家的神选系列。Day2根本不能做QAQ
题目描述:给定两个字符串集合,一个长度为n,另一个为m,求有多少个数字对i,j,满足xi+yj能由一个(n+m)/2的字符串旋转拼接而成
我们枚举长度较长的集合,那么我们的那个(n+m)/2的字符串就能确定了,接下来我们就可以对y的字符串hash掉然后枚举断点就能o(1)判断啦
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<map> 6 using namespace std; 7 #define p 17 8 #define maxn 8000010 9 typedef unsigned int uint; 10 map<uint,int> hash,used; 11 uint pow[maxn],c[maxn]; 12 string a[maxn],b[maxn]; 13 char ch[maxn]; 14 inline uint get(int l,int r){return c[r]-c[l-1]*pow[r-l+1];} 15 int main(){ 16 int s,t,n,m; 17 scanf("%d%d%d%d",&s,&t,&n,&m); 18 int l=(n+m)>>1; 19 for (int i=1;i<=s;i++) {scanf("%s",ch);a[i]=string(ch);} 20 for (int i=1;i<=t;i++) {scanf("%s",ch);b[i]=string(ch);} 21 if (n<m) { 22 for (int i=1;i<=max(s,t);i++) swap(a[i],b[i]); 23 swap(s,t); 24 swap(n,m); 25 } 26 for (int i=1;i<=t;i++) { 27 uint h=0; 28 for (int j=0;j<m;j++) h=h*p+b[i][j]-'a'; 29 hash[h]++; 30 } 31 int ans=0; 32 pow[0]=c[0]=1; 33 for (int i=1;i<=n+m;i++) pow[i]=pow[i-1]*p; 34 for (int i=1;i<=s;i++) { 35 used.clear(); 36 for (int j=0;j<n;j++) c[j+1]=c[j]*p+a[i][j]-'a'; 37 for (int j=1;j<=l;j++) { 38 uint h=get(j,l)*pow[j-1]+get(1,j-1); 39 if (used[h]) continue; 40 used[h]=1; 41 ans+=hash[h-get(l+1,n)*pow[m]]; 42 } 43 } 44 printf("%d ",ans); 45 return 0; 46 }