• TimusOJ2058. 100500 palidnromes 最小回文划分模板


    TimusOJ2058. 100500 palidnromes

    题意

    给定一个字符串(s),对于(s)的每个前缀求出它的最小回文划分数分别为奇数和偶数的个数。

    (|S|le 3cdot 10^5)

    Code

    #include<bits/stdc++.h>
    #define rep(i,x,n) for(int i=x;i<=n;i++)
    #define per(i,n,x) for(int i=n;i>=x;i--)
    #define sz(a) int(a.size())
    #define rson mid+1,r,p<<1|1
    #define pii pair<int,int>
    #define lson l,mid,p<<1
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define se second
    #define fi first
    using namespace std;
    const double eps=1e-8;
    const int mod=1e9+7;
    const int N=1e6+10;
    const int inf=1e9;
    int n;
    char s[N];
    int now,dp[N][2],g[N][2];
    struct PAM{
    	int ch[N][26],fail[N],len[N],dif[N],slink[N],tot,last;
    	int newnode(int x){
    		++tot;
    		memset(ch[tot],0,sizeof ch[tot]);
    		fail[tot]=0;len[tot]=x;
    		return tot;
    	}
    	void init(){
    		tot=-1;newnode(0);newnode(-1);
    		fail[0]=1;
    		last=0;
    	}
    	int gao(int x){
    		while(s[now-len[x]-1]!=s[now]) x=fail[x];
    		return x;
    	}
    	void insert(){
    		int p=gao(last);
    		int c=s[now]-'a';
    		if(!ch[p][c]){
    			int tmp=ch[gao(fail[p])][c];
    			ch[p][c]=newnode(len[p]+2);
    			fail[tot]=tmp;
    			dif[tot]=len[tot]-len[tmp];
    			if(dif[tot]==dif[tmp]) slink[tot]=slink[tmp];
    			else slink[tot]=tmp;
    		}
    		last=ch[p][c];
    	}
    	void qy(){
    		rep(i,0,n) dp[i][0]=dp[i][1]=inf;
    		dp[0][0]=0;
    		for(now=1;now<=n;now++){
    			insert();
    			for(int x=last;x>1;x=slink[x]){
    				g[x][0]=dp[now-dif[x]-len[slink[x]]][0];
    				g[x][1]=dp[now-dif[x]-len[slink[x]]][1];
    				if(dif[x]==dif[fail[x]]){
    					g[x][0]=min(g[x][0],g[fail[x]][0]);
    					g[x][1]=min(g[x][1],g[fail[x]][1]);
    				}
    				dp[now][0]=min(dp[now][0],g[x][1]+1);
    				dp[now][1]=min(dp[now][1],g[x][0]+1);
    			}
    			pii ans=mp(dp[now][1],dp[now][0]);
    			if(ans.fi>=inf) ans.fi=-1;
    			if(ans.se>=inf) ans.se=-2;
    			printf("%d %d
    ",ans.fi,ans.se);
    		}
    	}
    }P;
    int main(){
    	//ios::sync_with_stdio(false);
    	//freopen("in","r",stdin);
    	scanf("%s",s+1);
    	n=strlen(s+1);
    	P.init();
    	P.qy();
    	return 0;
    }
    
    
  • 相关阅读:
    HDU 2376 树形dp|树上任意两点距离和的平均值
    POJ2342 树形dp
    Codeforces 699D Fix a Tree 并查集
    第七届山东省ACM省赛
    [转]override和new的区别
    [转]C#的各种命名规范
    [转]DotNetBar.Bar作为容器使用的方法及Text更新原理
    [转]WPF: ShowDialog() 切换到其他应用窗口后,再切换回来无法让子窗口总在最上方
    c#校验主程序本身的MD5
    [转]WinForm登陆:窗体间的数据传递
  • 原文地址:https://www.cnblogs.com/xyq0220/p/14044926.html
Copyright © 2020-2023  润新知