1. 程式人生 > >BZOJ3075,LG3082 [USACO13MAR]項鏈Necklace

BZOJ3075,LG3082 [USACO13MAR]項鏈Necklace

main anywhere gin queue using des 希望 etc rocks

題意

Bessie the cow has arranged a string of N rocks, each containing a single letter of the alphabet, that she wants to build into a fashionable necklace.

Being protective of her belongings, Bessie does not want to share her necklace with the other cow currently living on her side of the barn. The other cow has a name that is a string of M characters, and Bessie wants to be sure that this length-M string does not occur as a contiguous substring anywhere within the string representing her necklace (otherwise, the other cow might mistakenly think the necklace is for her). Bessie decides to remove some of the rocks in her necklace so that the other cow‘s name does not appear as a substring. Please help Bessie determine the minimum number of rocks she must remove.

貝西收集了N顆石頭,每顆石頭上都有一個字母,貝西想把這些石頭做成項鏈。

貝西的身邊有另一只奶牛,這只奶牛的名字是一個長度為M的字符串,貝西不希望這只牛的名字出現在她的項鏈上(項鏈的子串),她想知道,最少刪掉幾顆石頭就可以避免這種情況發生。

分析

參照The_Virtuoso的題解。

首先如果用AC自動機做這道題顯然要把B串建在AC自動機上(AC自動機上就一個串好像有點浪費qwq)。要想B串不出現在A串中,只要把A串在AC自動機上跑,使它一直不遍歷到B串的終止節點就能保證B串不是A串的子串。想要最優解自然要dp,那麽就可以定義f[i][j]表示A串的第i個字符匹配到了AC自動機上第j個節點保留的最長長度。對於A串上的每一個字符可以刪除或者在AC自動機上往下走,最後用A串總長len減掉max{f[len][i]}就是最小刪除數了。

時間復雜度\(O(N M)\)

代碼

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read()
{
    rg T data=0;
    rg int w=1;
    rg char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data*w;
}
template<class T>il T read(rg T&x)
{
    return x=read<T>();
}
typedef long long ll;
using std::cerr;
using std::endl;

co int N=1e4+1,M=1e3+1;
char s[N],t[M];
namespace AC
{
    int tot;
    int ch[M][26],val[M];
    int fail[M];
    
    void ins(char s[],int n)
    {
        int u=0;
        for(int i=0;i<n;++i)
        {
            int k=s[i]-'a';
            if(!ch[u][k])
                ch[u][k]=++tot;
            u=ch[u][k];
        }
        val[u]=1;
    }
    
    void getfail()
    {
        std::queue<int>Q;
        for(int i=0;i<26;++i)
            if(ch[0][i])
                Q.push(ch[0][i]);
        while(Q.size())
        {
            int u=Q.front();Q.pop();
            for(int i=0;i<26;++i)
            {
                if(ch[u][i])
                {
                    fail[ch[u][i]]=ch[fail[u]][i];
                    Q.push(ch[u][i]);
                }
                else
                    ch[u][i]=ch[fail[u]][i];
            }
        }
    }
    
    int f[N][M];
    
    void solve(char s[],int n)
    {
        for(int i=0;i<n;++i)
        {
            int k=s[i]-'a';
            for(int j=0;j<=tot;++j)
            {
                if(!val[ch[j][k]])
                    f[i+1][ch[j][k]]=std::max(f[i+1][ch[j][k]],f[i][j]+1);
                if(!val[j])
                    f[i+1][j]=std::max(f[i+1][j],f[i][j]);
            }
        }
        int ans=0;
        for(int i=0;i<=tot;++i)
            ans=std::max(ans,f[n][i]);
        printf("%d\n",n-ans);
    }
}

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    scanf("%s",s);
    scanf("%s",t);
    AC::ins(t,strlen(t));
    AC::getfail();
    AC::solve(s,strlen(s));
    return 0;
}

BZOJ3075,LG3082 [USACO13MAR]項鏈Necklace