NOI2018お名前(68pts)

NOI2018お名前(68pts)

問題の意味

文字列に\(S \) 精製し\(M \)文字列\(T \)、Q \(T \)多数の連続的な非空の文字列でない\(S \)連続した非ヌル・ワード文字列
\ [| S | \ル5 \ times10 ^ 5、\和{T} \ le10 ^ 6 \]

問題の解決策

私たちは、にタイトルを置くことができます\(T \)部分文字列の異なる数がの性質には入っていません\(S \)私たちは二つの文字列築いてきた、登場\(SAM \) 最初の取得\(T \を)各プレフィックス\(S \)最大一致長\(L_iを\) )S(\ \ \(SAM \)は最長の共通のプレフィックスを決定することができます(L_iを\)\)、その後に\(T \)です\(SAMは\)の回答を求めています。我々は、ノードを定義\(I \)は、のコレクションを表し\(T \)などの位置が最初に現れる\(pos_i \) 次いで
\ [ANS = \ sum_ {I = 1} ^ {TOT} {MAX(0を、lenの[I] -max(LEN [リンク[I]、L_ {pos_i}))} \]

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
int read()
{
    int k=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) k=k*10+c-'0';return k*f;
}
const int N=2000055;
int n,m,tot,last,link[N],len[N],ch[N][26];
int Len[N];
char s[N],t[N];
void init()
{
    tot=last=0;
    link[0]=-1;len[0]=0;
}
void extend(int c)
{
    int p=last,cur=++tot;
    len[cur]=len[p]+1;
    for(;p!=-1&&!ch[p][c];p=link[p]) ch[p][c]=cur;
    if(p==-1) link[cur]=0;
    else 
    {
        int q=ch[p][c];
        if(len[p]+1==len[q]) link[cur]=q;
        else 
        {
            int nq=++tot;
            memcpy(ch[nq],ch[q],sizeof(ch[q]));
            len[nq]=len[p]+1;link[nq]=link[q];
            link[q]=link[cur]=nq;
            for(;p!=-1&&ch[p][c]==q;p=link[p]) 
                ch[p][c]=nq;
        }
    }
    last=cur;
}
struct sam
{       
    int tot=0,last=0,link[N],len[N],ch[N][26],pos[N];
    void init()
    {
        for(int i=0;i<=tot;i++)
            pos[i]=link[i]=len[i]=0,memset(ch[i],0,sizeof(ch[i]));
        tot=last=0;
        link[0]=-1;len[0]=0;
    }
    void extend(int c,int x)
    {
        int p=last,cur=++tot;
        len[cur]=len[p]+1;pos[cur]=x;
        for(;p!=-1&&!ch[p][c];p=link[p]) ch[p][c]=cur;
        if(p==-1) link[cur]=0;
        else 
        {
            int q=ch[p][c];
            if(len[p]+1==len[q]) link[cur]=q;
            else 
            {
                int nq=++tot;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                len[nq]=len[p]+1;link[nq]=link[q];pos[nq]=pos[q];
                link[q]=link[cur]=nq;
                for(;p!=-1&&ch[p][c]==q;p=link[p]) 
                    ch[p][c]=nq;
            }
        }
        last=cur;
    }
    ll query()
    {
        ll ans=0;
        for(int i=1;i<=tot;i++)
            ans+=max(0,len[i]-max(len[link[i]],Len[pos[i]]));;
        return ans;
    }
}sm;
int main()
{
    int a,b;
    scanf("%s",s);
    n=strlen(s);
    init();
    for(int i=0;i<n;i++)
        extend(s[i]-'a');
    m=read();
    for(int i=1;i<=m;i++)
    {
        scanf("%s",t);a=read();b=read();
        n=strlen(t);
        sm.init();
        int now=0,l=0;ll ans=0;
        for(int j=0;j<n;j++)
        {
            sm.extend(t[j]-'a',j);
            while(now&&!ch[now][t[j]-'a']) now=link[now],l=len[now];
            if(ch[now][t[j]-'a']) l++,now=ch[now][t[j]-'a'];
            Len[j]=l;
        }
        ans=sm.query();
        printf("%lld\n",ans);
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/waing/p/12243213.html
おすすめ