字符串专题:后缀数组

 后缀数组模板,复杂度:O(Nlog2n),用时要注意时间,这个比较耗时间

/*
后缀数组模板
asdfghjkl
ghj
对两个串匹配 有ghj返回1 必须连续
*/
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
int n,k;
int rank[100005],tmp[100005],sa[100005];
bool common_sa(int i,int j)
{
    if(rank[i]!=rank[j]) return rank[i]<rank[j];
    else
    {
        int ri=i+k<=n?rank[i+k]:-1;
        int rj=j+k<=n?rank[i+k]:-1;
        return ri<rj;
    }
}
void construct_sa(string s,int *sa)
{
    n=s.length();
    for(int i=0;i<=n;i++)
    {
        sa[i]=i;
        rank[i]=i<n?s[i]:-1;
    }
    for(k=1;k<=n;k*=2)
    {
        sort(sa,sa+n+1,common_sa);
        tmp[sa[0]]=0;
        for(int i=1;i<=n;i++)
        {
            tmp[sa[i]]=tmp[sa[i-1]]+(common_sa(sa[i-1],sa[i])?1:0);
        }
        for(int i=0;i<=n;i++)
        {
            rank[i]=tmp[i];
        }
    }
}
bool contain(string s,int *sa,string t)
{
    int a=0,b=s.length();
    while(b-a>1)
    {
        int c=(a+b)/2;
        if(s.compare(sa[c],t.length(),t)<0) a=c;
        else b=c;
    }
    return s.compare(sa[b],t.length(),t)==0;
}

int main()
{
    string mode,donser;
    while(cin>>donser>>mode)
    {
        n=donser.size();
        construct_sa(donser,sa);
        if(contain(donser,sa,mode)) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/dzzy/p/5475637.html