BZOJ 4085:[Sdoi2015]bigyration(SDOI 2015 round 2 Day 1)

别人家的神选系列。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\n",ans);
45     return 0;
46 }        

 

posted @ 2015-06-18 21:22  New_Godess  阅读(...)  评论(...编辑  收藏