基于后缀数组的字符串匹配

时间:2022-12-18 05:59:57

#include<bits/stdc++.h>
using namespace std;
const int MAX_N=1000005;
int n,k;
int Rank[MAX_N+1];
int tmp[MAX_N+1];
int sa[MAX_N+1];
bool compare_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[j+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,compare_sa);
        tmp[sa[0]]=0;
        for(int i=1;i<=n;i++)
        {
            tmp[sa[i]]=tmp[sa[i-1]]+(compare_sa(sa[i-1],sa[i])?1:0);
        }
        for(int i=0;i<=n;i++)
        {
            Rank[i]=tmp[i];
        }
    }
}
int 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 str,ss;
    cin>>str;//主串
    construct_sa(str,sa);
    while(cin>>ss)
    {
        cout<<contain(str,sa,ss)<<endl;
    } 
    return 0;
}