zoukankan      html  css  js  c++  java
  • 前缀和

    给你一个字符串,求所有长度为偶数的前缀在整个字符串出现的次数和。

    Input
    共一行,一个字符串s。
    Output
    共一行,输出一个整数,代表长度为偶数的前缀在整个字符串出现的次数和。|S|≤200000。
    Sample Input
    abababc
    Sample Output
    6

    Sol:

    先用Kmp算法求出nex[]数组,建立fail树然后统计子树大小.

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 200010
    #define maxn 410000
    using namespace std;
    #define int long long
    char s[N];
    int nex[N],len,p[N],ans;
    int pre[maxn],son[maxn],now[maxn],tot,col[maxn];
    void con(int a,int b)
    {
        pre[++tot]=now[a];
        now[a]=tot;
        son[tot]=b;
    }
    int dfs(int x) //统计子树大小 
    {
        int sz=1;
        for(int p=now[x];p;p=pre[p])
            sz+=dfs(son[p]);
        return sz;
    }
    main(){
       scanf("%s",s+1);
       len=strlen(s+1);
       nex[1]=0;
            for(int i=2,j=0;i<=len;i++)
            {
                while(j && s[j+1]!=s[i]) 
                j=nex[j];
                if(s[j+1]==s[i]) 
                    j++;
                nex[i]=j;//nex[8]=5
                con(j,i);//建一条边从j指向i,例如 5指向8,5是父亲点,8是子结点 
            }
       for(int i=1;i<=len;i++) 
            if(i%2==0)
                ans+=dfs(i);
       printf("%lld
    ",ans);
        
    }

     更好的做法是这样的:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 200010
    using namespace std;
    char s[N];
    int nex[N],len,p[N],ans;
    int main(){
        scanf("%s",s+1);len=strlen(s+1);nex[1]=0;
        for(int i=2,j=0;i<=len;i++){
            while(j && s[j+1]!=s[i]) j=nex[j];
            if(s[j+1]==s[i]) j++;
            nex[i]=j;
        }
        for(int i=1;i<=len;i++) p[i]=1;
        for(int i=len;i>=1;i--)  //统计子树大小,从后向前面做
    p[nex[i]]+=p[i]; for(int i=1;i<=len;i++)

    if(i%2==0) ans+=p[i]; printf("%d ",ans); }



    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll o,p[200011],sum[200011],len,ans,j;
    char a[200011];
    int main()
    {
    	// scanf("%lld",&o);
    	// while(o--)
    	// {
    	// 	memset(p,0,sizeof(p));
    	// 	memset(sum,0,sizeof(sum));
    		scanf("%s",a+1);
    		len=strlen(a+1);
    		ans=0;j=0;
    		for(ll i=1;i<len;i++)
    		{
    			while(j&&a[j+1]!=a[i+1])
    			    j=p[j];
    			if(a[j+1]==a[i+1])
    			    j++;
    			p[i+1]=j;
    		}
    		for(ll i=1;i<=len;i++)
    		if (i%2==0)
    		     sum[i]=sum[p[i]]+1;
    		else
    		
    		    sum[i]=sum[p[i]];
    		    // ans+=sum[i];
                    for(int i=1;i<=len;i++) ans+=sum[i];
    		printf("%lld
    ",ans);
    	// }
    	return 0;
    }
    

      

  • 相关阅读:
    创建分区表(按照年份分区,自动新增分区)
    flash rock me
    苹果有虫才好吃
    Evolutility改造支持oracle
    Nhibernate问题三则
    Html5+razor+jqmobile尝鲜
    配置Instantclient
    T4,Redmine,Nhibernate etc
    monotouch开发ios应用手记
    大文件及文件夹上传(续)
  • 原文地址:https://www.cnblogs.com/cutemush/p/12499488.html
Copyright © 2011-2022 走看看