• [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;
    }
    
    
    
    
    
    
  • 相关阅读:
    zoj 1033 与其说是搜索,不如说是枚举
    hdu 4294 数学分析+搜索
    新的篇章
    Silverlight 利用DataGrid行加载事件动态控制行列显示
    (转)Excel中“不同的单元格格式太多”问题解决方法
    EasyUI tree的三种选中状态
    JS监听手机返回键
    Silverlight ComBox获取当前选中项的值
    DataGrdid 利用结果集反向转换成数据List
    silverlight 动态设置下拉框选中值
  • 原文地址:https://www.cnblogs.com/xcxc82/p/14253190.html
Copyright © 2020-2023  润新知