• 题解 [NOI2016] 优秀的拆分


    题目传送门

    Description

    给出一个长度为 (n) 的字符串,问有多少个子串,满足可以写成 (AABB) 的形式。

    (nle 3 imes 10^4)

    Solution

    md,直接 hash 暴力就能获得 (95) 分的好成绩。

    考虑正解,我们设 (a_i) 表示以 (i) 结尾能写成 (AA) 形式的后缀个数,(b_i) 表示以 (i) 开头能写成 (AA) 形式的前缀个数。

    我们考虑计算出长度为 (2k) 的字符串产生的贡献。我们每 (k) 个就设置一个端点,那么可以想到的是一个合法的字符串一定会经过且只经过两个相邻端点。

    所以我们对于两个相邻端点考虑,如果两者的前缀的最长公共后缀 lcs 和两者的后缀的最长公共前缀 lcp 满足 (lcs+lcp-1ge k) 那么显然 (i-lcs+1sim i-lcs+1+lcs+lcp-1-k) 都是可以作为开头的点,那么就可以区间增加这一段的 (b)(a) 数组同理。

    求 lcs 和 lcp 直接 SA 就好了。时间复杂度 (Theta(nlog n+nln n))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define MAXN 30005
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    
    char s[MAXN];
    
    struct SA{
    	int n,m,num,x[MAXN],y[MAXN],c[MAXN],sa[MAXN],rk[MAXN],st[MAXN][21];
    	void clear(){
    		memset (x,0,sizeof (x));
    		memset (y,0,sizeof (y));
    	}
    	int query (int l,int r){
    		if (l == r) return n - sa[l] + 1;
    		if (l > r) swap (l,r);++ l;
    		int k = log2 (r - l + 1);
    		return min (st[l][k],st[r - (1 << k) + 1][k]);
    	} 
    	void Build (){
    		n = strlen (s + 1);
    		m = 26;for (Int i = 1;i <= m;++ i) c[i] = 0;
    		for (Int i = 1;i <= n;++ i) x[i] = s[i] - 'a' + 1,c[x[i]] ++;
    		for (Int i = 1;i <= m;++ i) c[i] += c[i - 1];
    		for (Int i = 1;i <= n;++ i) sa[c[x[i]] --] = i;
    		for (Int k = 1;k <= n;k <<= 1){
    			num = 0;for (Int i = n - k + 1;i <= n;++ i) y[++ num] = i;
    			for (Int i = 1;i <= n;++ i) if (sa[i] > k) y[++ num] = sa[i] - k;
    			for (Int i = 1;i <= m;++ i) c[i] = 0;for (Int i = 1;i <= n;++ i) c[x[i]] ++;for (Int i = 1;i <= m;++ i) c[i] += c[i - 1];
    			for (Int i = n;i >= 1;-- i) sa[c[x[y[i]]] --] = y[i],y[i] = 0;swap (x,y),x[sa[1]] = num = 1;
    			for (Int i = 2;i <= n;++ i) num += !(y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]),x[sa[i]] = num;
    			m = num;if (m == n) break; 
    		}
    		for (Int i = 1;i <= n;++ i) rk[sa[i]] = i;
    		for (Int i = 1,k = 0;i <= n;++ i){
    			if (rk[i] == 1) k = 0;
    			else{
    				if (k) -- k;
    				int j = sa[rk[i] - 1];
    				while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) ++ k;
    			}
    			st[rk[i]][0] = k; 
    		}
    		for (Int j = 1;(1 << j) <= n;++ j) for (Int i = 1;i + (1 << j) - 1 <= n;++ i) st[i][j] = min (st[i][j - 1],st[i + (1 << j - 1)][j - 1]);
    	}
    	int fuckit (int a,int b){return query (rk[a],rk[b]);}
    }S,T;
    
    int n,a[MAXN],b[MAXN];
    
    void Work (){
    	S.clear(),T.clear();
    	scanf ("%s",s + 1),n = strlen (s + 1);
    	S.Build(),reverse (s + 1,s + n + 1),T.Build();
    	memset (a,0,sizeof (a)),memset (b,0,sizeof (b));
    	for (Int len = 1;(len << 1) <= n;++ len)
    		for (Int i = len;i + len <= n;i += len){
    			int l = i,r = i + len,L = n - (r - 1) + 1,R = n - (l - 1) + 1;
    			int lcs = T.fuckit (L,R),lcp = S.fuckit (l,r);
    			lcp = min (lcp,len),lcs = min (lcs,len - 1);
    			if (lcs + lcp >= len){
    				b[i - lcs] ++,b[i - lcs + (lcp + lcs - len + 1)] --;
    				a[r + lcp - (lcp + lcs - len + 1)] ++,a[r + lcp] --;
    			}
    		}
    	for (Int i = 1;i <= n;++ i) a[i] += a[i - 1],b[i] += b[i - 1];
    	long long ans = 0;for (Int i = 1;i < n;++ i) ans += 1ll * a[i] * b[i + 1];
    	write (ans),putchar ('
    ');
    }
    
    signed main(){
    //	freopen ("P1117_6.in","r",stdin);
    	int T;read (T);
    	while (T --> 0) Work ();
     	return 0;
    }
    
  • 相关阅读:
    Rasp技术介绍与实现(一)
    青藤云安全细述:三大云安全工具(CASB、CSPM、CWPP)的使用场景
    CWPP产品市场演进
    Global CyberSecurity Landscape
    Scala学习之路 (五)Scala的关键字Lazy
    Scala学习之路 (四)Scala的数组、映射、元组、集合
    Scala学习之路 (三)Scala的基本使用
    Scala学习之路 (二)使用IDEA开发Scala
    Scala学习之路 (一)Scala的安装
    Azkaban学习之路 (三)Azkaban的使用
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/14443979.html
Copyright © 2020-2023  润新知