JZOJ5462 好文章
Description
nodgd写了一篇文章,自认为这是一篇好文章。nodgd的文章由𝑛个小写英文字母组成。文章的一个子串指的是文章中的一段连续的字母,子串的长度就是这一段的字母个数。nodgd在文章中用了排比、对偶、前后照应之类的手法,所以就有很多个子串是相同或者相近的。为了向大家证明这是一篇好文章,nodgd决定给自己的文章进行评分。nodgd首先确定了一个整数𝑚,然后统计出文章中有多少个不相同的长度为𝑚的子串,这个数量就是文章的评分。
然而,nodgd懒得老老实实计算这个评分了,就把任务丢给了你。
然而,nodgd懒得老老实实计算这个评分了,就把任务丢给了你。
Input
第一行包含两个整数𝑛,𝑚,表示文章的长度和需要统计的子串长度。
第二行包含一个长度为𝑛的只包含小写字母的字符串。
第二行包含一个长度为𝑛的只包含小写字母的字符串。
Output
输出一行一个整数,表示文章的评分。
Sample Input
输入1: 5 3 aaaab 输入2: 9 3 abcabacba
Sample Output
输出1: 2 样例解释1: 长度为3的子串有3个,分别是aaa,aaa,aab,其中不同的只有2个。 输出2: 7 样例解释2 共有7个长度为3的子串,每个长度为3的子串都不同。
Data Constraint
对于30%的数据,1≤𝑚≤𝑛≤200;
对于50%的数据,1≤𝑚≤𝑛≤2000;
对于另外20%的数据,1≤𝑚≤50≤𝑛≤200000;
对于100%的数据,1≤𝑚≤𝑛≤200000。
对于50%的数据,1≤𝑚≤𝑛≤2000;
对于另外20%的数据,1≤𝑚≤50≤𝑛≤200000;
对于100%的数据,1≤𝑚≤𝑛≤200000。
Solution
字符串hash,为了提高容错率所以用双hash。
1 #include<cstdio> 2 #include<algorithm> 3 #define N 1000000007 4 #define M 1000000009 5 using namespace std; 6 struct arr 7 { 8 long long x,y; 9 }h[2000000],s[200000]; 10 int n,m,a[3000000]; 11 long long p1,p2; 12 bool cmp(arr a,arr b) 13 { 14 return a.x<b.x||a.x==b.x&&a.y<b.y; 15 } 16 int main() 17 { 18 scanf("%d%d",&n,&m); 19 int i=0; 20 while (i<n) 21 { 22 char ch; 23 scanf("%c",&ch); 24 int t=(int)ch; 25 if (t<=122&&t>=97) 26 { 27 i++; 28 a[i]=t-96; 29 } 30 } 31 p1=53;p2=97; 32 for (int i=2;i<=m;i++) 33 { 34 p1=(p1*53)%N; 35 p2=(p2*97)%M; 36 } 37 for (int i=1;i<=n;i++) 38 { 39 h[i].x=(h[i-1].x*53+a[i])%N; 40 h[i].y=(h[i-1].y*97+a[i])%M; 41 } 42 for (int i=1;i<=n-m+1;i++) 43 { 44 s[i].x=(h[i+m-1].x-h[i-1].x*p1)%N; 45 s[i].y=(h[i+m-1].y-h[i-1].y*p2)%M; 46 while (s[i].x<0) s[i].x=s[i].x+N; 47 while (s[i].y<0) s[i].y=s[i].y+M; 48 } 49 sort(s+1,s+n-m+2,cmp); 50 int ans=0; 51 for (int i=1;i<=n-m+1;i++) 52 if (s[i].x!=s[i-1].x||s[i].y!=s[i-1].y) 53 ans++; 54 printf("%d\n",ans); 55 }