bzoj4032 / luoguP4112 [HEOI2015】共通文字列が最短(DP + Aサフィックスオートマトンオートマトン配列)ではありません

bzoj Luogu

問題解決の時間

2文字の小文字の文字列$ A $、$ B $は、計算してください:

(1)$ A $最短ストリングは、$ B $のサブストリングではありません

(2)$ A $最短のサブ、それは$ Bドル配列ではありません

(3)$ A $配列は、それがない$ B $のサブ最短であります

(4)$ A $配列は、それが$ Bドル配列最短ではありません

四の水問題、一つの質問以上の4つの質問つ星

フォロールーチンが$ A $ $ B $を一致させることですので、見つけるために$ A $からのすべてのようにまず、

そのため、最初のSAMと$ B $シーケンスオートマトンを構築します。

オートマトン配列:$次の[I] [CH] $ $ I $配列は純粋にマッチングするために、発生の最初の文字位置$ $ CHの次のビットを表しています。

直接、すべての試合に$ A $の暴力に(1)、限り不一致が答えを更新してから飛び出すように、SAMの$ B $で始まります。

(2)配列オートマトンで変化させました。

(3)$ DP $ J $位置、このように形成された最短の配列長にSAMの$ B $に一致するように形成された[I] [J] $意味配列$ A $フロント$ I $文字、これは非常に古典的なDPアップです。

(4)配列オートマトンで変化させました。

#include<bits/stdc++.h>
using namespace std;
namespace RKK
{
const int N=2011,inf=0x3f3f3f3f;
int n1;char s1[N];
int n2;char s2[N];
struct remilia{int tranc[26],len,pre;};
struct sakuya
{
    remilia s[N<<1];
    int fin,size;
    sakuya(){fin=size=1;}
    void ins(int ch)
    {
        int npx,npy,lpx,lpy;
        npx=++size;
        s[npx].len=s[fin].len+1;
        for(lpx=fin;lpx&&!s[lpx].tranc[ch];lpx=s[lpx].pre) s[lpx].tranc[ch]=npx;
        if(!lpx) s[npx].pre=1;
        else
        {
            lpy=s[lpx].tranc[ch];
            if(s[lpy].len==s[lpx].len+1) s[npx].pre=lpy;
            else
            {
                npy=++size;
                s[npy]=s[lpy];
                s[npy].len=s[lpx].len+1;
                s[lpy].pre=s[npx].pre=npy;
                while(s[lpx].tranc[ch]==lpy)
                {
                    s[lpx].tranc[ch]=npy;
                    lpx=s[lpx].pre;
                }
            }
        }
        fin=npx;
    }
    void insert(char *str,int sl)
    {
        for(int i=1;i<=sl;i++)
            ins(str[i]-'a');
    }
}sam;
struct flandre
{
    int ne[N][26],tmp[26];
    void insert(char *s,int sl)
    {
        for(int i=sl;i>=0;i--)
            memcpy(ne[i],tmp,104),tmp[s[i]-'a']=i;
    }
}sem;
void solve1()
{
    int ans=inf;
    for(int sp=1;sp<=n1;sp++)
    {
        int px=1;
        for(int i=sp;i<=n1;i++)
        {
            if(!sam.s[px].tranc[s1[i]-'a']){ans=min(ans,i-sp+1);break;}
            px=sam.s[px].tranc[s1[i]-'a'];
        }
    }
    printf("%d\n",ans==inf?-1:ans);
}
void solve2()
{
    int ans=inf;
    for(int sp=1;sp<=n1;sp++)
    {
        int px=0;
        for(int i=sp;i<=n1;i++)
        {
            if(!sem.ne[px][s1[i]-'a']){ans=min(ans,i-sp+1);break;}
            px=sem.ne[px][s1[i]-'a'];
        }
    }
    printf("%d\n",ans==inf?-1:ans);
}
int dp[N<<1];
void solve3()
{
    int ans=inf;
    memset(dp,0x3f,sizeof(dp));
    dp[1]=0;
    for(int i=1;i<=n1;i++)
    {
        for(int x=sam.size;x;x--)
        {
            if(sam.s[x].tranc[s1[i]-'a']) dp[sam.s[x].tranc[s1[i]-'a']]=min(dp[sam.s[x].tranc[s1[i]-'a']],dp[x]+1);
            else ans=min(ans,dp[x]+1);
        }
    }
    printf("%d\n",ans==inf?-1:ans);
}
void solve4()
{
    int ans=inf;
    memset(dp,0x3f,sizeof(dp));
    dp[0]=0;
    for(int i=1;i<=n1;i++)
    {
        for(int x=n2;x>=0;x--)
        {
            if(!sem.ne[x][s1[i]-'a']) ans=min(ans,dp[x]+1);
            else dp[sem.ne[x][s1[i]-'a']]=min(dp[sem.ne[x][s1[i]-'a']],dp[x]+1);
        }
    }
    printf("%d\n",ans==inf?-1:ans);
}
int Iris()
{
    scanf("%s%s",s1+1,s2+1),n1=strlen(s1+1),n2=strlen(s2+1);
    sam.insert(s2,n2),sem.insert(s2,n2);
    solve1(),solve2(),solve3(),solve4();
    return 0;
}
}
int main(){return RKK::Iris();}

おすすめ

転載: www.cnblogs.com/rikurika/p/12079153.html