1 条题解

  • 0
    @ 2025-8-24 22:53:08

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar FFTotoro
    龙猫

    搬运于2025-08-24 22:53:08,当前版本为作者最后更新于2023-12-19 21:55:47,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    典型的思路简单实现稍复杂的 trie + map 字符串模拟题。

    使用官方题解做法;附参考代码。

    下令 Sstring 类型,* 为通配符。

    显然 N 在后面的情况和 N 在前面的情况本质上是一样的,可以进行一些处理后用同一种方法做。但是记得数组要清空

    先考虑 N 在前面的情况,令记录串为 NZH 的形式:

    1. NZH 在给定复制串中出现过,可以匹配的复制串有且仅有如下几种情况:

      • 复制串为 NZH:使用 map<S,int> 统计;

      • 复制串为 NP*PZH 非空前缀:使用字典树统计;

      • 复制串为 N*SSZH 非空后缀:同上;

      • 复制串为 N**:使用一个变量统计;

    2. NZH 在给定复制串中未出现过(NZ*N*H 出现过),可以匹配的复制串有且仅有如下几种情况:

      • 复制串为 NP*PZ 非空前缀:使用字典树统计;

      • 复制串为 N*SSH 非空后缀:同上;

      • 复制串为 N**:使用一个变量统计。

    再考虑 N 在中间的情况,令记录串为 QNH 的形式:

    1. QNH 在给定复制串中出现过,可以匹配的复制串有且仅有如下几种情况:

      • 复制串为 QNH:使用 map<pair<S,S>,int> 统计;

      • 复制串为 QN*:使用 map<S,int> 统计;

      • 复制串为 *NH:同上;

      • 复制串为 *N*:使用一个变量统计;

    2. QNH 在给定复制串中未出现过(QN**NH 出现过),可以匹配的复制串有且仅有如下几种情况:

      • 复制串为 QN*:使用 map<S,int> 统计;

      • 复制串为 *NH:同上;

      • 复制串为 *N*:使用一个变量统计。

    几种情况取个最大值即可。

    放代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef string S;
    namespace Trie{
      int t[2][1000001][26],c[2][1000001],o[2];
      void C(){
        memset(t,0,sizeof(t));
        memset(c,0,sizeof(c));
        o[0]=o[1]=0;
      }
      void I(int b,S s){
        int p=0;
        for(char i:s)
          if(t[b][p][i-97])p=t[b][p][i-97];
          else p=t[b][p][i-97]=++o[b];
        c[b][p]++;
      }
      int Q(int b,S s){
        int p=0,w=0;
        for(char i:s)
          if(t[b][p][i-97])w+=c[b][p=t[b][p][i-97]];
          else break;
        return w;
      }
    } // 字典树模板
    int main(){
      ios::sync_with_stdio(false);
      int n; cin>>n;
      vector<vector<pair<S,S> > > a(3);
      while(n--){
        S q,z,h; cin>>q>>z>>h;
        if(q=="N")a[0].emplace_back(z,h);
        else if(z=="N")a[1].emplace_back(q,h);
        else{
          if(q=="Q")q="H";
          else reverse(q.begin(),q.end());
          reverse(z.begin(),z.end());
          a[2].emplace_back(z,q);
          // 把 N 在后面的情况变成 N 在前面
        }
      } // 处理输入的字符串
      vector<int> c(3);
      for(int i=0;i<3;i++)
        if(int ca=0,cb=0,w=0;i&1){
          map<S,int> m1,m2;
          map<pair<S,S>,int> m3;
          for(auto [x,y]:a[i]){
            if(x!="Q"){
              if(y!="H")m3[make_pair(x,y)]++;
              else m1[x]++;
            }
            else if(y!="H")m2[y]++;
            else w++;
          } // 统计
          for(auto [x,y]:a[i]){
            if(x!="Q"){
              if(y!="H")c[i]=max(c[i],m1[x]+m2[y]+m3[make_pair(x,y)]);
              else ca=max(ca,m1[x]);
            }
            else if(y!="H")cb=max(cb,m2[y]);
          } // 计算答案
          c[i]=max(c[i],ca+cb)+w;
        } // N 在中间
        else{
          Trie::C();
          map<S,int> m;
          for(auto [x,y]:a[i]){
            S z=y; reverse(z.begin(),z.end());
            if(x!="Z"){
              if(y!="H")m[x+y]++;
              else Trie::I(0,x);
            }
            else if(y!="H")Trie::I(1,z);
            else w++;
          } // 统计
          for(auto [x,y]:a[i]){
            S e=x+y,r=e,z=y;
            reverse(r.begin(),r.end());
            reverse(z.begin(),z.end());
            e.pop_back(),r.pop_back();
            if(x!="Z"){
              if(y!="H")c[i]=max(c[i],m[x+y]+Trie::Q(0,e)+Trie::Q(1,r));
              else ca=max(ca,Trie::Q(0,x));
            }
            else if(y!="H")cb=max(cb,Trie::Q(1,z));
          } // 计算答案
          c[i]=max(c[i],ca+cb)+w;
        } // N 在前面
      cout<<*max_element(c.begin(),c.end())<<endl;
      return 0;
    }
    
    • 1

    信息

    ID
    9499
    时间
    2000ms
    内存
    1024MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者