zoukankan      html  css  js  c++  java
  • SPOJ-SUBST1 New Distinct Substrings 后缀数组

    SPOJ-SUBST1 New Distinct Substrings 后缀数组

    题意

    给定一个字符串,求其中本质不同的子串

    [T leq 20 \ |s| leq 50000 ]

    分析

    直接找不同的有点麻烦,不妨反着考虑本质相同的子串的个数

    height数组的含义是(sa[i])(sa[i - 1])的后缀的公共前缀的长度。这个公共前缀是本质相同的,所以需要减去

    [ans = n imes (n + 1) / 2 - sum height[i] ]

    代码

    char ss[maxn];
    int s[maxn];
    int sa[maxn],t[maxn],t2[maxn],c[maxn],n;
    int len;
    
    void build_sa(int m){
    	int *x = t,*y = t2;
    	for(int i = 0;i < m;i++) c[i] = 0;
    	for(int i = 0;i < n;i++) c[x[i] = s[i]]++;
    	for(int i = 1;i < m;i++) c[i] += c[i -1];
    	for(int i = n - 1;i >= 0;i--) sa[--c[x[i]]] = i;
    	for(int k = 1;k <= n;k <<= 1){
    		int p = 0;
    		for(int i = n - k;i < n;i++) y[p++] = i;
    		for(int i = 0;i < n;i++) if(sa[i] >= k) y[p++] = sa[i] - k;
    		for(int i = 0;i < m;i++) c[i] = 0;
    		for(int i = 0;i < n;i++) c[x[y[i]]]++;
    		for(int i = 0;i < m;i++) c[i] += c[i - 1];
    		for(int i = n - 1;i >= 0;i--) sa[--c[x[y[i]]]] = y[i];
    		swap(x,y);
    		p = 1;
    		x[sa[0]] = 0;
    		for(int i = 1;i < n;i++)
    			x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p - 1:p++;
    		if(p >= n) break;
    		m = p;
    	}
    }
    
    int rak[maxn],height[maxn];
    
    void getHeight(){
    	int k = 0;
    	for(int i = 0;i < n;i++) rak[sa[i]] = i;
    	for(int i = 0;i < n;i++){
    		if(k) k--;
    		int j = sa[rak[i] - 1];
    		while(s[i + k] == s[j + k]) k++;
    		height[rak[i]] = k;
    	}
    }
    
    int main(){
    	int T = readint();
    	while(T--){
    		scanf("%s",ss);
    		n = strlen(ss);
    		for(int i = 0;i < n;i++){
    			s[i] = ss[i];
    		}
    		s[n++] = 0;
    		build_sa(200);
    		getHeight();
    		ll res = (ll)n * (n - 1) / 2;
    		for(int i = 0;i <= n ;i++){
    			res -= height[i];
    		}
    		cout << res << '
    ';
    		n++;
    		memset(sa,0,sizeof(int) * n);
    		memset(rak,0,sizeof(int) * n);
    		memset(t,0,sizeof(int) * n);
    		memset(t2,0,sizeof(int) * n);
    		memset(height,0,sizeof(int) * n);
    		memset(s,0,sizeof(int) * n);
    	}
    }
    
  • 相关阅读:
    Win32串口API
    Windows核心编程 第4章 进程
    大家都来吐槽下12306的网站bug吧
    HttpRequest模拟Post和Get提交代码
    jquery.masonry + jquery.infinitescroll 实现瀑布流布局
    三层架构之泛型应用
    listView 中,大图标时,各个图标之间间距的控制
    Windows Phone APP的设计过程
    分享三个小故事
    最值得创业者聆听的10大TED演讲(中文字幕视频)
  • 原文地址:https://www.cnblogs.com/hznumqf/p/14062797.html
Copyright © 2011-2022 走看看