码迷,mamicode.com
首页 > 其他好文 > 详细

[蒟蒻修炼计划][bzoj3670][2014湖北省队互测week2]似乎在梦中见过的样子

时间:2016-07-08 17:59:43      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:

Description

已知一个字符串S,求它有多少个形如A+B+A的子串(len(A)>=k,len(B)>=1 )

Input

第一行一个字符串,第二行一个数 k

Output

仅一行一个数,表示满足条件的子串数。

Sample Input

aaaaa
1

Sample Output

6

HINT

对于 100%的数据:n<=15000 , k<=100,且字符集为所有小写字母。

Solution

这道题时限15s,明显O(n^2)可以过。那么如果枚举某一端形成新的子串,用kmp的思想去处理的话,就可以过了。

那具体要如何处理这个子串呢?假设我们枚举左端点l,s长度为r,则形成的新子串为s[l...r]

由题意我们可以知道,如果s[l...i]=s[j-i+l...j](i-l+1)>=kl-1+(i-l+1)*2+1<=j,那么s[l...j]就是一个满足条件的子串,那么这道题就明显和Noi2014动物园很像了。

如果直接暴力用next[]找满足条件的前缀,实现会变成O(n^3)

所以这个地方得继续用kmp的思想:当发现现在的i不满足条件时,可以用next[]向前寻找满足条件的i

这样的话,每次都是从满足(j-1)的条件的i开始寻找,于是时间复杂度就压到了O(n^2)

 1 #include<set> 
 2 #include<cmath>
 3 #include<ctime>
 4 #include<queue>
 5 #include<stack>
 6 #include<cstdio>
 7 #include<vector>
 8 #include<cstring>
 9 #include<cstdlib>
10 #include<iostream>
11 #include<algorithm>
12 #define N 15002
13 using namespace std;
14 int next[N],n,k,ans;
15 char a[N];
16 inline void get_next(char a[]){
17     for(int i=2,j=0;a[i];i++){
18         while(j&&a[i]!=a[j+1]) j=next[j];
19         j+=(a[i]==a[j+1]);
20         next[i]=j;
21     }
22     for(int i=2,j=0;a[i];i++){
23         while(j&&a[i]!=a[j+1]) j=next[j];
24         j+=(a[i]==a[j+1]);
25         while(j&&j*2>=i) j=next[j];
26         if(j>=k) ans++;
27     }
28 }
29 inline void init(){
30     scanf("%s%d",a+1,&k);
31     n=strlen(a+1);n-=(k<<1);
32     for(int i=0;i<n;i++)
33         get_next(a+i);
34     printf("%d",ans);
35 }
36 int main(){
37     freopen("dream.in","r",stdin);
38     freopen("dream.out","w",stdout);
39     init();
40     fclose(stdin);
41     fclose(stdout);
42     return 0;
43 }

[蒟蒻修炼计划][bzoj3670][2014湖北省队互测week2]似乎在梦中见过的样子

标签:

原文地址:http://www.cnblogs.com/AireenYe/p/5653802.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!