• spoj Distinct Substrings 后缀数组


    给定一个字符串,求不相同的子串的个数。

    假如给字符串“ABA";排列的子串可能:

    A       B      A

    AB       BA

    ABA  

    共3*(3+1)/2=6种;

    后缀数组表示时:

    A

    ABA

    BA

    对于A和AB height[i]=1;

    表明一个长度公共,所以ABA中多出现了A这个子串,所以6-1=5;

    对于ABA BA height[i]=0,所以不需要减去。

    最后答案为5;

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<string>
    #include<map>
    #define LL long long
    using namespace std;
    #define maxn 1100
    int wa[maxn],wb[maxn],wv[maxn],WS[maxn];
    int cmp(int *r,int a,int b,int l)
    {return r[a]==r[b]&&r[a+l]==r[b+l];}
    void da(int *r,int *sa,int n,int m)
    {
        int i,j,p,*x=wa,*y=wb,*t;
        for(i=0;i<m;i++) WS[i]=0;
        for(i=0;i<n;i++) WS[x[i]=r[i]]++;
        for(i=1;i<m;i++) WS[i]+=WS[i-1];
        for(i=n-1;i>=0;i--) sa[--WS[x[i]]]=i;
        for(j=1,p=1;p<n;j*=2,m=p)
        {
            for(p=0,i=n-j;i<n;i++) y[p++]=i;
            for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
            for(i=0;i<n;i++) wv[i]=x[y[i]];
            for(i=0;i<m;i++) WS[i]=0;
            for(i=0;i<n;i++) WS[wv[i]]++;
            for(i=1;i<m;i++) WS[i]+=WS[i-1];
            for(i=n-1;i>=0;i--) sa[--WS[wv[i]]]=y[i];
            for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
                x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
        }
        return;
    }
    int Rank[maxn],height[maxn];
    void calheight(int *r,int *sa,int n)
    {
        int i,j,k=0;
        for(i=1;i<=n;i++) Rank[sa[i]]=i;
        for(i=0;i<n;height[Rank[i++]]=k)
            for(k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++);
        return;
    }
    int r[maxn],sa[maxn];
    char s[maxn];
    void slove(int len)
    {
        int i,j,ans;
        ans=(len+1)*len/2;//总共排列的个数
        for(i=1;i<=len;i++)
        {
            ans-=height[i];//相同的部分长度表示这段重复出现了。并且出现了height[i]个组合。
        }
        cout<<ans<<endl;
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            cin>>s;
            int len=strlen(s);
            for(int i=0;i<len;i++)
                r[i]=s[i];
            r[len]=0;
            da(r,sa,len+1,125);
            calheight(r,sa,len);
            slove(len);
        }
    }
  • 相关阅读:
    AtomicInteger
    Android利用ViewPager实现滑动广告板
    modelsim实用教程--前言
    信号的抽取和插值
    FPGA与simulink联合实时环路系列——实验三 按键key
    FPGA与simulink联合实时环路系列——实验二LED
    FPGA与simulink联合实时环路系列——实验一 测试
    FPGA与simulink联合实时环路系列—开篇
    格雷码原理与Verilog实现
    基于FPGA的飞机的小游戏
  • 原文地址:https://www.cnblogs.com/sweat123/p/4802926.html
Copyright © 2020-2023  润新知