JZOJ5462 好文章

Description

  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。

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 }
View Code

 

 
posted @ 2018-08-14 21:37  kasiruto  阅读(120)  评论(0编辑  收藏