• 2019徐州网络赛G. Colorful String【回文树】


    传送门

    题意

    定义一个字符串的值为字符串中不同字符的种数,求一个字符串的所有回文子串的值的和。

    题解

    算是回文自动机的板子题,可惜之前做的时候没学,直接构建回文树,dfs统计就行了。
    写这个还是为了完善一下回文自动机的模板,之前写的那个模板不好用。

    代码

    #include <iostream>
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    using namespace std;
    typedef long long LL;
    const int N=3e5+10;
    char s[N];
    int n;
    LL ans;
    struct PAM{
    	int tr[N][26],fail[N],len[N],cnt[N],tot,last,n;
    	int getfail(int x){
    		while(s[n]!=s[n-len[x]-1]) x=fail[x];
    		return x;
    	}
    	void init(char *s){
    		n=tot=last=0;
    		cnt[0]=len[0]=cnt[1]=0;
    		memset(tr[0],0,sizeof(tr[0]));
    		memset(tr[1],0,sizeof(tr[1]));
    		fail[0]=1;
    		len[++tot]=-1;
    		for(n=1;s[n]!='';n++){
    			int c=s[n]-'a',cur=getfail(last);
    			if(!tr[cur][c]){
    				len[++tot]=len[cur]+2;cnt[tot]=0;
    				memset(tr[tot],0,sizeof(tr[tot]));
    				fail[tot]=tr[getfail(fail[cur])][c];
    				tr[cur][c]=tot;
    			}
    			last=tr[cur][c];
    			cnt[last]++;
    		}
    		for(int i=tot;i>=0;i--) cnt[fail[i]]+=cnt[i];
    	}
    	int count,vis[26];
    	void dfs(int u){
    		ans+=count*cnt[u];
    		for(int i=0;i<26;i++){
    			if(!tr[u][i]) continue;
    			vis[i]++;if(vis[i]==1) count++;
    			dfs(tr[u][i]);
    			vis[i]--;if(!vis[i]) count--;
    		}
    	}
    }pam;
    
    
    int main(){
    	scanf("%s",s+1);
    	pam.init(s);
    	pam.dfs(0);
    	pam.dfs(1);
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    JDBC 精度
    AIX性能监控
    OID View
    Deci and Centi Seconds parsing in java
    SpringMVC @RequestBody问题:Unrecognized field , not marked as ignorable
    Linux SNMP oid
    MySQL 监控
    SVN 搭建
    C# 之 继承
    storm单词计数 本地运行
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/12529732.html
Copyright © 2020-2023  润新知