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
aaaaa
1
【样例输入 2】
abcabcabc
2
Sample Output
【样例输出 1】
6
【样例输出 2】
8
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 }