Description
给你一个字符串,求所有长度为偶数的前缀在整个字符串出现的次数和。
Input
共一行,一个字符串s。
Output
共一行,输出一个整数,代表长度为偶数的前缀在整个字符串出现的次数和。|S|≤200000。
Sample Input
abababc
Sample Output
6
sol:方法同string,只计算长度为偶数的前缀。
fail树的代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define N 200010 5 #define maxn 410000 6 using namespace std; 7 #define int long long 8 char s[N]; 9 int nex[N],len,p[N],ans; 10 int pre[maxn],son[maxn],now[maxn],tot,col[maxn]; 11 void con(int a,int b) 12 { 13 pre[++tot]=now[a]; 14 now[a]=tot; 15 son[tot]=b; 16 } 17 int dfs(int x) //统计子树大小 18 { 19 int sz=1; 20 for(int p=now[x];p;p=pre[p]) 21 sz+=dfs(son[p]); 22 return sz; 23 } 24 main(){ 25 scanf("%s",s+1); 26 len=strlen(s+1); 27 nex[1]=0; 28 for(int i=2,j=0;i<=len;i++) 29 { 30 while(j && s[j+1]!=s[i]) 31 j=nex[j]; 32 if(s[j+1]==s[i]) 33 j++; 34 nex[i]=j;//nex[8]=5 35 con(j,i);//建一条边从j指向i,例如 5指向8,5是父亲点,8是子结点 36 } 37 for(int i=1;i<=len;i++) 38 if(i%2==0) 39 ans+=dfs(i); 40 printf("%lld ",ans); 41 42 }
逆循环代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define N 200010 5 using namespace std; 6 char s[N]; 7 int nex[N],len,p[N],ans; 8 int main(){ 9 scanf("%s",s+1);len=strlen(s+1);nex[1]=0; 10 for(int i=2,j=0;i<=len;i++){ 11 while(j && s[j+1]!=s[i]) j=nex[j]; 12 if(s[j+1]==s[i]) j++; 13 nex[i]=j; 14 } 15 for(int i=1;i<=len;i++) p[i]=1; 16 for(int i=len;i>=1;i--) //统计子树大小,从后向前面做 17 p[nex[i]]+=p[i]; 18 for(int i=1;i<=len;i++) 19 20 if(i%2==0) ans+=p[i]; 21 printf("%d ",ans); 22 }