bzoj2580 [Usaco 2012 Jan] Video Game AC 자동기 + dp

5082 단어 bzojAC 로봇DP
뚜렷한 dp, f[i][j]를 설정하면 i번째 위치로 가는 것을 표시하고trie의 j번째 노드의 최대 답안을 표시하며 각 끝을 +1으로 하고 접두사와 접두사를 구하여 직접 업데이트하면 됩니다.
#include
#include
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define inf 0xc3c3c3c3
using namespace std;
const int N=1e5+5;
int ch[N][5];
char s[N];
int tag[N],cnt=1;
int fail[N],q[N];
int f[1005][500];
int num[N];
int n,K;
inline void add(int x,int k)
{
    memset(ch[cnt],0,sizeof(ch[cnt]));
    num[cnt]=0;
    ch[x][k]=cnt++;
}
inline void ins()
{
    int n=strlen(s);
    int x=0;
    fo(i,0,n-1)
    {
        int c=s[i]-'A';
        if (!ch[x][c])add(x,c);
         x=ch[x][c];
    }
    num[x]++;
}
inline void acmach()
{
    int w=1;
    int x;
    q[0]=0; 
    fo(i,0,w-1)
    { 
        x=q[i];
        num[x]+=num[fail[x]];
        fo(j,0,2)
        if (ch[x][j])
        {
            q[w++]=ch[x][j];
            if (!x)fail[ch[x][j]]=0;
            else fail[ch[x][j]]=ch[fail[x]][j];
        }
        else ch[x][j]=ch[fail[x]][j];
    }
}
inline void dp()
{
    memset(f,0xc3,sizeof(f));
    f[0][0]=0;
    fo(i,0,K-1)
    fo(j,0,cnt-1)
    if (f[i][j]!=inf)
    fo(k,0,2)
    {
        int x=ch[j][k];
        f[i+1][x]=max(f[i+1][x],f[i][j]+num[x]);
    }//f[i][ch[j][k]]=max(f[i][ch[j][k]],f[i-1][j]+num[ch[j][k]]);
}
int main()
{
    scanf("%d%d",&n,&K);
    num[0]=0;
    memset(ch[0],0,sizeof(ch[0]));
    cnt=1;
    fo(i,1,n)
    {
        scanf("%s",s);
        ins();
    }
    acmach();
    dp();
    int ans=0;
    fo(i,0,cnt-1)ans=max(ans,f[K][i]);
    printf("%d
"
,ans); }

좋은 웹페이지 즐겨찾기