2 条题解

  • 0
    @ 2025-10-8 17:06:39

    //code by cff_0102 (luogu uid 542457),also see https://www.luogu.com.cn/article/5un1s8c2

    #include<bits/stdc++.h>
    using namespace std;
    const int N=309,K=1010;
    int tr[N][3],cnt=0,pre[N],ed[N];
    void ins(string s){
        int nw=0;
        for(int i=0;i<s.length();i++){
            int c=s[i]-'A';
            if(tr[nw][c]==0)tr[nw][c]=++cnt;
            nw=tr[nw][c];
        }
        ed[nw]++;
    }
    void build(){
        queue<int>q;
        for(int i=0;i<3;i++)if(tr[0][i])q.push(tr[0][i]);
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int y=0;y<3;y++){
                if(tr[x][y]==0)tr[x][y]=tr[pre[x]][y];
                else{
                    pre[tr[x][y]]=tr[pre[x]][y];
                    q.push(tr[x][y]);
                }
            }
            ed[x]+=ed[pre[x]];//记得加上沿着 fail 边往上跳能跳到多少个字符串的末尾
        }
    }
    int dp[K][N];//输入 i 个字符,最后停在 AC 自动机的点 j 时能获得几分
    void solve(int kk){
        for(int i=0;i<=kk;i++)dp[i][0]=0;
        for(int i=0;i<kk;i++){
            for(int j=0;j<=cnt;j++){
                for(int k=0;k<3;k++){//接下来往哪走呢 
                    dp[i+1][tr[j][k]]=max(dp[i+1][tr[j][k]],dp[i][j]+ed[tr[j][k]]);
                }
            }
        }
    }
    int main(){
        ios::sync_with_stdio(0);cin.tie(0);
        int n,k;cin>>n>>k;
        for(int i=1;i<=n;i++){
            string s;cin>>s;
            ins(s);
        }
        build();
        memset(dp,-0x3f,sizeof(dp));
        solve(k);
        int ans=0;
        for(int i=0;i<=cnt;i++){
            ans=max(ans,dp[k][i]);
        }
        cout<<ans;
        return 0;
    }
    
    • 0
      @ 2025-10-8 17:06:31
      //code by cff_0102 (luogu uid 542457),also see https://www.luogu.com.cn/article/5un1s8c2
      #include<bits/stdc++.h>
      using namespace std;
      const int N=309,K=1010;
      int tr[N][3],cnt=0,pre[N],ed[N];
      void ins(string s){
          int nw=0;
          for(int i=0;i<s.length();i++){
              int c=s[i]-'A';
              if(tr[nw][c]==0)tr[nw][c]=++cnt;
              nw=tr[nw][c];
          }
          ed[nw]++;
      }
      void build(){
          queue<int>q;
          for(int i=0;i<3;i++)if(tr[0][i])q.push(tr[0][i]);
          while(!q.empty()){
              int x=q.front();q.pop();
              for(int y=0;y<3;y++){
                  if(tr[x][y]==0)tr[x][y]=tr[pre[x]][y];
                  else{
                      pre[tr[x][y]]=tr[pre[x]][y];
                      q.push(tr[x][y]);
                  }
              }
              ed[x]+=ed[pre[x]];//记得加上沿着 fail 边往上跳能跳到多少个字符串的末尾
          }
      }
      int dp[K][N];//输入 i 个字符,最后停在 AC 自动机的点 j 时能获得几分
      void solve(int kk){
          for(int i=0;i<=kk;i++)dp[i][0]=0;
          for(int i=0;i<kk;i++){
              for(int j=0;j<=cnt;j++){
                  for(int k=0;k<3;k++){//接下来往哪走呢 
                      dp[i+1][tr[j][k]]=max(dp[i+1][tr[j][k]],dp[i][j]+ed[tr[j][k]]);
                  }
              }
          }
      }
      int main(){
          ios::sync_with_stdio(0);cin.tie(0);
          int n,k;cin>>n>>k;
          for(int i=1;i<=n;i++){
              string s;cin>>s;
              ins(s);
          }
          build();
          memset(dp,-0x3f,sizeof(dp));
          solve(k);
          int ans=0;
          for(int i=0;i<=cnt;i++){
              ans=max(ans,dp[k][i]);
          }
          cout<<ans;
          return 0;
      }
      • 1

      信息

      ID
      4245
      时间
      1000ms
      内存
      128MiB
      难度
      10
      标签
      递交数
      8
      已通过
      5
      上传者