• 题解 [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;
    }
    
  • 相关阅读:
    Objective--C三大特性:封装,继承,多态(零碎笔记)
    零碎的知识点
    Objective--C之《文件操作》练习代码
    Objective--C的Foundation frame之NSMutableDictionary代码
    Objective--C的Foundation frame之NSMutableArray代码
    Objective--C随笔2016年8月7日
    关于OC中的委托delegate
    javascript 绝对路径工具类
    IE 弹出框处理经验
    InputStream和OutputStream 何时使用
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/14443979.html
Copyright © 2020-2023  润新知