bzoj3620 似乎在梦中见过的样子

Description

“Madoka,不要相信 QB!”伴随着 Homura 的失望地喊叫,Madoka 与 QB 签订了契约.
这是 Modoka 的一个噩梦,也同时是上个轮回中所发生的事.为了使这一次 Madoka 不再与 QB签订契约,Homura 决定在刚到学校的第一天就解决 QB.然而,QB 也是有许多替身的(但在第八话中的剧情显示它也有可能是无限重生的),不过,意志坚定的 Homura 是不会放弃的——她决定
消灭所有可能是 QB 的东西.现在,她已感受到附近的状态,并且把它转化为一个长度为 n 的字符串交给了学 OI 的你.
现在你从她的话中知道 , 所有形似于 A+B+A 的字串都是 QB 或它的替身 , 且len(A)>=k,len(B)>=1 (位置不同其他性质相同的子串算不同子串,位置相同但拆分不同的子串算同一子串),然后你必须尽快告诉 Homura 这个答案——QB 以及它的替身的数量.

Input

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

Output

仅一行一个数 ans,表示 QB 以及它的替身的数量

Sample Input

【样例输入 1】
aaaaa
1
【样例输入 2】
abcabcabc
2

Sample Output

【样例输出 1】
6

【样例输出 2】
8

HINT 

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

 

正解:$kmp$算法。

$NOI2014$动物园的弱化版。。

首先这题正解好像就是$O(n^{2})$的算法,于是直接枚举合法字符串的左端点,从左端点开始的字串跑一遍$kmp$,注意这道题的匹配条件有一个限制,那就是前缀与后缀匹配的长度小于串长$/2$。于是我们另外开一个$nt$数组,记录长度小于$n/2$的前缀和后缀的匹配,如果失配就直接跳$next$。具体操作可以看代码。。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <queue>
10 #include <stack>
11 #include <map>
12 #include <set>
13 #define inf (1<<30)
14 #define N (200010)
15 #define il inline
16 #define RG register
17 #define ll long long
18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
19 
20 using namespace std;
21 
22 int nxt[N],nt[N],k,len,ans;
23 char s[N],c[N];
24 
25 il int gi(){
26     RG int x=0,q=1; RG char ch=getchar();
27     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
28     if (ch=='-') q=-1,ch=getchar();
29     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
30     return q*x;
31 }
32 
33 il void work(){
34     scanf("%s",s+1),len=strlen(s+1),k=gi();
35     for (RG int p=1;p<=len;++p){
36     RG int l=0; for (RG int i=p;i<=len;++i) c[++l]=s[i];
37     for (RG int i=2,j;i<=l;++i){
38         j=nxt[i-1]; while (j && c[j+1]!=c[i]) j=nxt[j];
39         if (c[j+1]==c[i]) nxt[i]=j+1; else nxt[i]=0; j=nt[i-1];
40         while (j && (c[j+1]!=c[i] || j>((i-1)>>1)-1)) j=nxt[j];
41         if (c[j+1]==c[i] && j<=((i-1)>>1)-1) nt[i]=j+1; else nt[i]=0;
42         if (nt[i]>=k) ++ans;
43     }
44     }
45     printf("%d\n",ans); return;
46 }
47 
48 int main(){
49     File("3620");
50     work();
51     return 0;
52 }

 

posted @ 2017-07-06 19:50  wfj_2048  阅读(203)  评论(0编辑  收藏  举报