zoukankan      html  css  js  c++  java
  • 不同子串个数

    I.不同子串个数

    后缀数组在处理子串问题时往往有奇效,因为后缀的前缀即是子串,而后缀数组正是按照前缀排序的后缀

    回到本题。因为后缀的前缀是子串,则一条后缀与其它所有后缀的LCP的最长长度,即是这条后缀的前缀子串中所有被重复计数的串的数量。

    我们掏出求得的\(ht\)数组。初学SA时大家一定接触过一个重要的\(\text{LCP Lemma}\),即\(\operatorname{LCP}(i,j)=\min\limits_{i\leq j\leq k}ht_j\)。我们考虑当前后缀与其它任何一条串的LCP,发现它的表达式都包含\(ht_i\),即\(ht_i\)即为LCP的最长长度。则只需要求出所有子串数量减去\(\sum\limits_{i=1}^{n}ht_i\)即可。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll res;
    int n,m,sa[1001000],rk[1001000],buc[1001000],x[1001000],y[1001000],ht[1001000];
    char s[1001000];
    void SA(){
    	for(int i=1;i<=n;i++)buc[x[i]=s[i]]++;
    	for(int i=1;i<=m;i++)buc[i]+=buc[i-1];
    	for(int i=n;i;i--)sa[buc[x[i]]--]=i;
    	for(int k=1;k<=n;k<<=1){
    		int 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=0;i<=m;i++)buc[i]=0;
    		for(int i=1;i<=n;i++)buc[x[y[i]]]++;
    		for(int i=1;i<=m;i++)buc[i]+=buc[i-1];
    		for(int i=n;i;i--)sa[buc[x[y[i]]]--]=y[i],y[i]=0;
    		swap(x,y);
    		x[sa[1]]=1;
    		num=1;
    		for(int i=2;i<=n;i++)x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
    		if(num==n)break;
    		m=num;
    	}
    }
    void HT(){
    	for(int i=1;i<=n;i++)rk[sa[i]]=i;
    	int k=0;
    	for(int i=1;i<=n;i++){
    		if(rk[i]==1)continue;
    		if(k)k--;
    		int j=sa[rk[i]-1];
    		while(j+k<=n&&i+k<=n&&s[j+k]==s[i+k])k++;
    		ht[rk[i]]=k;
    	}
    }
    int main(){
    	scanf("%d%s",&n,s+1),m='z';
    	SA(),HT();
    //	for(int i=0;i<n;i++)printf("%d ",sa[i]);puts("");
    	for(int i=1;i<=n;i++)res+=(n-sa[i]+1)-ht[i];
    	printf("%lld\n",res);
    	return 0;
    }
    

  • 相关阅读:
    Fiddler-常用技巧
    Fiddler-工作原理
    C语言-EOF和feof()判断文件结尾的区别
    C语言-一个fopen函数中未使用二进制模式(b)引发的血案
    VIM-不常用或不知道的技巧
    C语言-srand种子详解
    C语言-字符串操作函数
    C语言-Makefile经典教程(掌握这些足够)
    分布拟合——正态/拉普拉斯/对数高斯/瑞利 分布
    曲线拟合——(2)拉普拉斯/瑞利/对数正态 曲线
  • 原文地址:https://www.cnblogs.com/Troverld/p/14602298.html
Copyright © 2011-2022 走看看