• [CF932G]Palindrome Partition(PAM回文划分dp)


    题面

    https://codeforces.com/problemset/problem/932/G

    题解

    前置知识

    在做此题之前,需要了解利用PAM在(O(n log n))时间内解决最小回文划分、回文划分数等回文划分相关dp的方法(见上面链接)

    有了这个基础,我们再做此题。由于"第一个与最后一个相同,第二个与倒数第二个相同……"这样的条件极难dp,所以我们考虑转化题意。

    如何做呢?首先如果给出的字符串长度为奇数,那肯定是0啦。

    否则的话,将字符串的前后半部分拆开,将后半部分翻转,再把它们“拉链式”合并。以本题样例1为例:

    就成功地将原题那个恶心的条件变成了求回文串划分方案数。样例1的答案ab|cd|cd|ab对应着新序列的abba|cddc。

    另外有一个地方与之前的回文划分dp不同,就是这里的回文划分中的每一个回文串长度必须是偶数。不过这个也好解决,dp时将所有奇数位的dp值都设成0就可以了。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define ll long long
    #define rg register
    #define In inline
    
    const int N = 1e6;
    const ll mod = 1e9 + 7;
    
    namespace ModCalc{
    	In void Inc(ll &x,ll y){
    		x += y;if(x >= mod)x -= mod;
    	}
    	In void Dec(ll &x,ll y){
    		x -= y;if(x < 0)x += mod;
    	}
    	In ll Add(ll x,ll y){
    		Inc(x,y);return x;
    	}
    	In ll Sub(ll x,ll y){
    		Dec(x,y);return x;
    	}
    }
    using namespace ModCalc;
    
    char t[N+5],s[N+5];
    int n;
    ll f[N+5],g[N+5],slink[N+5],diff[N+5];
    
    struct PAM{
    	ll nx[N+5][26],len[N+5],fail[N+5];
    	int last,cnt;
    	void clear(){
    		cnt++;
    		len[1] = -1;
    		fail[0] = fail[1] = 1;
    	}
    	void extend(char c,int n){
    		int id = c - 'a';
    		int p = last;
    		while(s[n-len[p]-1] != s[n])p = fail[p];
    		if(!nx[p][id]){
    			cnt++;
    		 	len[cnt] = len[p] + 2;
    		 	int q = fail[p];
    		 	while(s[n-len[q]-1] != s[n])q = fail[q];
    		 	fail[cnt] = nx[q][id];
    		 	nx[p][id] = cnt;
    		 	diff[cnt] = len[cnt] - len[fail[cnt]];
    		 	if(diff[cnt] != diff[fail[cnt]])
    		 		slink[cnt] = fail[cnt];
    	 		else
    		 		slink[cnt] = slink[fail[cnt]];
    		} 
    		last = nx[p][id];
    		p = last;
    		while(p >= 2){
    			g[p] = f[n-len[slink[p]]-diff[p]];
    			if(diff[p] == diff[fail[p]])Inc(g[p],g[fail[p]]);
    			if(!(n & 1))Inc(f[n],g[p]);
    			p = slink[p];
    		}
    	}	
    }P;
    
    int main(){
    	scanf("%s",t + 1);
    	n = strlen(t + 1);
    	if(n & 1){
    		puts("0");return 0;
    	}
    	P.clear();
    	ll _n = 0;
    	for(rg int i = 1;(i << 1) <= n;i++)s[++_n] = t[i],s[++_n] = t[n+1-i];
    	f[0] = 1;
    	for(rg int i = 1;i <= n;i++)P.extend(s[i],i);
    	cout<<f[n]<<endl;
    	return 0;
    }
    
  • 相关阅读:
    php多态
    ssl certificate problem: self signed certificate in certificate chain
    test plugin
    open specific port on ubuntu
    junit vs testng
    jersey rest service
    toast master
    use curl to test java webservice
    update folder access
    elk
  • 原文地址:https://www.cnblogs.com/xh092113/p/12398609.html
Copyright © 2020-2023  润新知