zoukankan      html  css  js  c++  java
  • [NOIP2020] 字符串匹配

    题目链接

    大致题意

    给一个字符串(S),求(S=(AB)^iC)的方案数,其中(F(A)≤F(C)),(F(S))表示字符串 (S) 中出现奇数次的字符的数量

    分析

    (cnt_i)表示奇数字符数小于等于(i)(A)的个数

    枚举(AB)的长度,然后用(KMP)(next)数组去枚举循环次数(i),将小于等于(C)中奇数字符的数量的(A)的方案数,也就是(cnt_{j})((j)(C)中出现奇数次字符从数量)加到答案中,并更新一下(cnt)

    最坏时间复杂度(O(n×(logn+26))),不开(O2) (92)~(96)pts,开(O2)稳过

    (code)

    /*
    xcxc82
    */
    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = (1<<20)+10;
    inline int read(){
    	int X=0; bool flag=1; char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
    	while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
    	if(flag) return X;return ~(X-1);
    }
    int pre[MAXN],suf[MAXN],next[MAXN],pre_value[30];
    int buc[30];
    bool vis[30];
    int T,n;
    long long ans;
    string s;
    void clear(){
    	ans = 0;
    	memset(vis,false,sizeof(vis));
    	memset(pre,0,sizeof(pre));
    	memset(suf,0,sizeof(suf));
    	memset(next,0,sizeof(next));
    	memset(buc,0,sizeof(buc));
    	memset(pre_value,0,sizeof(pre_value));
    } 
    void kmp(){
    	int j = 0;
    	for(int i=2;i<=n;i++){
    		while(j>0&&s[i]!=s[j+1]) j = next[j];
    		if(s[i]==s[j+1]) j++;
    		next[i] = j;
    	}
    }
    signed main(){
    	T = read();
    	while(T--){
    		int cnt = 0;
    		clear();
    		cin>>s;
    		s = ' '+s;
    		n = s.length()-1;
    		for(int i=1;i<=n;i++){
    			if(!vis[s[i]-'a'+1]) vis[s[i]-'a'+1] = 1,cnt++;
    		}
    		kmp();
    		for(int i=1;i<=n;i++){
    			int now = s[i]-'a'+1;
    			buc[now]++;
    			if(buc[now]&1) pre[i] = pre[i-1]+1;
    			else pre[i] = pre[i-1]-1;
    		}
    		memset(buc,0,sizeof(buc));
    		for(int i=n;i>=1;i--){
    			int now = s[i]-'a'+1;
    			buc[now]++;
    			if(buc[now]&1) suf[i] = suf[i+1]+1;
    			else suf[i] = suf[i+1]-1;
    		}
    		for(int i=1;i<n;i++){
    			if(i>1){
    				for(int j=i;j<n;j+=i){
    					if((i%(j-next[j])==0&&j/(j-next[j])>1)||(j==i))
    					ans+=(long long)(pre_value[suf[j+1]]);
    					else break;
    				}
    			}
    			for(int j=pre[i];j<=cnt;j++){
    				pre_value[j]++;
    			}
    		}
    		printf("%lld
    ",ans);
    	}
       return 0;
    }
    
    
    
    
    
    
  • 相关阅读:
    eval命令的使用
    declare与typeset的使用
    【线型DP模板】最上上升子序列(LIS),最长公共子序列(LCS),最长公共上升子序列(LCIS)
    【线型DP】【LCS】UVA_10635 Prince and Princess
    【经典DP】洛谷 P2782 友好城市
    HDU-1051/POJ-1065 Wooden sticks 木棍子(动态规划 LIS 线型动归)
    BZOJ3659 Which Dreamed It
    CF300D Painting Square
    CF632E Thief in a Shop 和 CF958F3 Lightsabers (hard)
    CF528D Fuzzy Search 和 BZOJ4259 残缺的字符串
  • 原文地址:https://www.cnblogs.com/xcxc82/p/14253190.html
Copyright © 2011-2022 走看看