• SPOJ DISUBSTR ——后缀数组


    【题目分析】

        后缀数组模板题。

        由于height数组存在RMQ的性质。

        那么对于一个后缀,与前面相同的串总共有h[i]+sa[i]个。然后求和即可。

    【代码】(模板来自Claris,这个板子太漂亮了)

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    
    #include <map>
    #include <set>
    #include <queue>
    #include <string>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define maxn 500005
    #define N 500005
    #define inf 0x3f3f3f3f
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    
    void Finout()
    {
        #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    //    freopen("out.txt","w",stdout);
        #endif
    }
    
    int Getint()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    struct Suffix_Array{
    	char s[maxn];
    	int rk[maxn],sa[maxn],h[maxn],tmp[maxn],cnt[maxn];
    	void build(int n,int m)
    	{
    		int i,j,k;n++;
    		F(i,0,2*5+4) rk[i]=sa[i]=h[i]=tmp[i]=0;
    		F(i,0,m-1) cnt[i]=0;
    		F(i,0,n-1) cnt[rk[i]=s[i]]++;
    		F(i,1,m-1) cnt[i]+=cnt[i-1];
    		F(i,0,n-1) sa[--cnt[rk[i]]]=i;
    		for (k=1;k<=n;k<<=1)
    		{
    			F(i,0,n-1)
    			{
    				j=sa[i]-k;
    				if (j<0) j+=n;
    				tmp[cnt[rk[j]]++]=j;
    			}
    			sa[tmp[cnt[0]=0]]=j=0;
    			F(i,1,n-1)
    			{
    				if (rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k]) cnt[++j]=i;
    				sa[tmp[i]]=j;
    			}
    			memcpy(rk,sa,n*sizeof(int));
    			memcpy(sa,tmp,n*sizeof(int));
    			if (j>=n-1) break;
    		}
    		for (j=rk[h[i=k=0]=0];i<n-1;++i,++k)
    			while (~k&&s[i]!=s[sa[j-1]+k]) h[j]=k--,j=rk[sa[j]+1];
    	}
    }arr;
    
    int main()
    {
    	int tt;
    	scanf("%d",&tt);
    	while (tt--)
    	{
    	    scanf("%s",arr.s);
    	    int ans=0,l=strlen(arr.s);
    	    arr.s[l]=0;
    	    arr.build(l,128);
    	    ans+=l-arr.sa[1];
    	    F(i,2,l) ans+=l-arr.sa[i]-arr.h[i];
    	    cout<<ans<<endl;
    	}
    }
    

      UPD(2017.3.30):回来再看自动机的时候重新写了一遍,感觉求h数组的部分不是很直观,所以改掉了。

    #include <map>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define ll long long
    #define mp make_pair
    
    #define maxn 5005
    
    struct Suffix_Array{
    	int s[maxn];
    	int rk[maxn],cnt[maxn],sa[maxn],tmp[maxn],h[maxn];
    	void build(int n,int m)
    	{
    		int i,j,k; n++;
    		F(i,0,2*n+5) tmp[i]=sa[i]=rk[i]=h[i]=0;
    		F(i,0,m-1) cnt[i]=0;
    		F(i,0,n-1) cnt[rk[i]=s[i]]++;
    		F(i,1,m-1) cnt[i]+=cnt[i-1];
    		F(i,0,n-1) sa[--cnt[rk[i]]]=i;
    		for (k=1;k<=n;k<<=1)
    		{
    			F(i,0,n-1)
    			{
    				j=sa[i]-k;
    				if (j<0) j+=n;
    				tmp[cnt[rk[j]]++]=j;
    			}
    			sa[tmp[cnt[0]=0]]=j=0;
    			F(i,1,n-1)
    			{
    				if (rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k]) cnt[++j]=i;
    				sa[tmp[i]]=j;
    			}
    			memcpy(rk,sa,n*sizeof (int));
    			memcpy(sa,tmp,n*sizeof (int));
    			if (j>=n-1) break;
    		}
    		for (i=k=0;i<n;h[rk[i++]]=k)
    			for (k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k];k++);
    	}
    }SA;
    
    char ss[maxn];
    int ans=0,tt;
    
    int main()
    {
    	scanf("%d",&tt);
    	while (tt--)
    	{
    		ans=0;
    		scanf("%s",ss);
    		int n=strlen(ss);
    		F(i,0,n-1) SA.s[i]=ss[i]; SA.s[n]=0;
    		SA.build(n,256);
    		F(i,1,n) ans+=n-SA.sa[i]-SA.h[i];
    		printf("%d
    ",ans);
    	}
    }
    

      

  • 相关阅读:
    rac11.2.0.4私网公网修改
    OGG应用复制进程报错OGG 01161
    顺序容器vector拷贝使用总结
    C++迭代器(STL迭代器)
    C++容器(STL容器)
    win10桌面和手机的扩展API,判断是否有实体后退键API
    python Django 之 Model ORM inspectdb(数据库表反向生成)
    flask框架-大结局
    flask框架-下
    flask框架-中
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6240019.html
Copyright © 2020-2023  润新知