zoukankan      html  css  js  c++  java
  • [HDU5421]Victor and String(PAM)

    题面

    http://acm.hdu.edu.cn/showproblem.php?pid=5421

    题解

    前置知识

    这道题很好地证明了PAM是可以双向添加的。

    如果只有操作2、3、4,那就是PAM模板而已。现在考虑1怎么做。

    发现操作1和2、以及3,4的维护并不冲突。可以仿效结尾加点的操作,具体如下:

    • 维护lastl,lastr表示当前的字符串的最长前缀回文子串和最长后缀回文子串。(可以为全串)
    • 更新fail,next的操作毫不影响,因为本来转移时回文串就是要左右两边各加一个字符
    • lastl、lastr有可能会相互影响,就是当lastl或者lastr其中之一求出来为全串的时候,那么也要把另一个也赋为全串。

    更详细操作可见代码。

    代码

    #include<iostream>
    #include<cstring>
    
    using namespace std;
    
    #define rg register
    #define In inline
    #define ll long long
    
    const int N = 1e5;
    
    In ll read(){
    	ll s = 0,ww = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-')ww = -1;ch = getchar();}
    	while('0' <= ch && ch <= '9'){s = 10 * s + ch - '0';ch = getchar();}
    	return s * ww;
    }
    
    In void write(ll x){
    	if(x < 0)putchar('-'),x = -x;
    	if(x > 9)write(x / 10);
    	putchar('0' + x % 10);
    }
    
    char s[2*N+5];
    int l,r;
    
    struct PAM{
    	int nx[N+5][26],fail[N+5],len[N+5];
    	ll dep[N+5];
    	int cnt,lastl,lastr;
    	ll sum;
    	void clear(){
    		cnt = 1;
    		fail[0] = fail[1] = 1;
    		memset(nx[0],0,sizeof(nx[0]));
    		memset(nx[1],0,sizeof(nx[1]));
    		len[0] = 0,len[1] = -1;
    		lastl = lastr = 0;
    		sum = 0;
    	}
    	void create(){
    		cnt++;
    		memset(nx[cnt],0,sizeof(nx[cnt]));
    	}
    	void extendl(char c,int n){
    		int id = c - 'a';
    		int p = lastl;
    		while(s[l+len[p]+1] != s[l])p = fail[p];
    		if(!nx[p][id]){
    			create();
    			len[cnt] = len[p] + 2;
    			int q = fail[p];
    			while(s[l+len[q]+1] != s[l])q = fail[q];
    			fail[cnt] = nx[q][id];
    			dep[cnt] = dep[fail[cnt]] + 1;
    			nx[p][id] = cnt;
    		}
    		lastl = nx[p][id];
    		sum += dep[lastl];
    		if(len[lastl] == r - l + 1)lastr = lastl;
    	}
    	void extendr(char c,int n){
    		int id = c - 'a';
    		int p = lastr;
    		while(s[r-len[p]-1] != s[r])p = fail[p];
    		if(!nx[p][id]){
    			create();
    			len[cnt] = len[p] + 2;
    			int q = fail[p];
    			while(s[r-len[q]-1] != s[r])q = fail[q];
    			fail[cnt] = nx[q][id];
    			dep[cnt] = dep[fail[cnt]] + 1;
    			nx[p][id] = cnt;
    		}
    		lastr = nx[p][id];
    		sum += dep[lastr];
    		if(len[lastr] == r - l + 1)lastl = lastr;
    	}
    }P;
    
    int n;
    
    int main(){
    	while(~scanf("%d",&n)){
    		P.clear();
    		memset(s,0,sizeof(s));
    		l = N,r = N - 1;
    		while(n--){
    			int opt = read();
    			if(opt <= 2){
    				char c = getchar();
    				while(c < 'a' || c > 'z')c = getchar();
    				if(opt == 1)s[--l] = c,P.extendl(c,l);
    				else s[++r] = c,P.extendr(c,r);
    			}
    			else{
    				if(opt == 3)write(P.cnt - 1),putchar('
    ');
    				else write(P.sum),putchar('
    ');
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    MFC CDialog/CDialogEx DoModal ALT
    yum和apt-get用法及区别
    ubuntu 12.04 source.list 源更新
    elasticsearch 优化
    TRIE树
    数据统计经验浅谈
    机器学习
    python 读取libsvm文件
    spark 参数调优
    python中的一些函数
  • 原文地址:https://www.cnblogs.com/xh092113/p/12398733.html
Copyright © 2011-2022 走看看