zoukankan      html  css  js  c++  java
  • CF1327G Letters and Question Marks [AC 自动机+状压dp]

    憨批题,怎么我CF的时候就做不出这个题啊啊啊啊啊啊啊

    题意:

    给你 (k)(k)个串 (t_i) 以及价值 (c_i)((sum |t_i| leq 10^3)),然后给你一个串 (s)((|s|leq 4 imes 10^5)),(s) 中最多包含 (14)(?),字符集是 (14),每个 (?) 不能取到相同字符,对于每一种填充字符的方式,求最大的(sum F(s,t_i) imes c_i)

    sol:

    ACAutoMaton 傻子题。

    考虑到 AC 自动机如果把 (ed_{fa_i}) 信息加到 (ed_i) 上,那么 (ed_i) 就是 (i) 节点对应的字符串包含的所有子串的信息。
    我们考虑到最多有 (14)(?),所以这个玩意最多被分成了 (14) 段。那么显然我们可以直接计算对于每个节点 (j) 在第 (i) 段会变成 AC 自动机上的哪个节点 (nxt_{j,i}),以及计算(j) 走过第 (i) 段的贡献 (sum_{j,i} = sum ed_p),然后就可以 (dp) 了。

    // clang-format off
    // powered by c++11
    // by Isaunoya
    #include<bits/stdc++.h>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define Rep(i,x,y) for(register int i=(x);i>=(y);--i)
    using namespace std;using db=double;using ll=long long;
    using uint=unsigned int;using ull=unsigned long long;
    using pii=pair<int,int>;
    #define Tp template
    #define fir first
    #define sec second
    Tp<class T>void cmax(T&x,const T&y){if(x<y)x=y;}Tp<class T>void cmin(T&x,const T&y){if(x>y)x=y;}
    #define all(v) v.begin(),v.end()
    #define sz(v) ((int)v.size())
    #define pb emplace_back
    Tp<class T>void sort(vector<T>&v){sort(all(v));}Tp<class T>void reverse(vector<T>&v){reverse(all(v));}
    Tp<class T>void unique(vector<T>&v){sort(all(v)),v.erase(unique(all(v)),v.end());}inline void reverse(string&s){reverse(s.begin(),s.end());}
    const int SZ=1<<23|233;
    struct FILEIN{char qwq[SZ],*S=qwq,*T=qwq,ch;
    #ifdef __WIN64
    #define GETC getchar
    #else
    inline char GETC(){return(S==T)&&(T=(S=qwq)+fread(qwq,1,SZ,stdin),S==T)?EOF:*S++;}
    #endif
    inline FILEIN&operator>>(char&c){while(isspace(c=GETC()));return*this;}inline FILEIN&operator>>(string&s){s.clear();while(isspace(ch=GETC()));if(!~ch)return*this;s=ch;while(!isspace(ch=GETC())&&~ch)s+=ch;return*this;}
    inline FILEIN&operator>>(char*str){char*cur=str;while(*cur)*cur++=0;cur=str;while(isspace(ch=GETC()));if(!~ch)return*this;*cur=ch;while(!isspace(ch=GETC())&&~ch)*++cur=ch;*++cur=0;return*this;}
    Tp<class T>inline void read(T&x){bool f=0;while((ch=GETC())<48&&~ch)f^=(ch==45);x=~ch?(ch^48):0;while((ch=GETC())>47)x=x*10+(ch^48);x=f?-x:x;}
    inline FILEIN&operator>>(int&x){return read(x),*this;}inline FILEIN&operator>>(ll&x){return read(x),*this;}inline FILEIN&operator>>(uint&x){return read(x),*this;}inline FILEIN&operator>>(ull&x){return read(x),*this;}
    inline FILEIN&operator>>(double&x){read(x);bool f=x<0;x=f?-x:x;if(ch^'.')return*this;double d=0.1;while((ch=GETC())>47)x+=d*(ch^48),d*=.1;return x=f?-x:x,*this;}
    }in;
    struct FILEOUT{const static int LIMIT=1<<22;char quq[SZ],ST[233];int sz,O,pw[233];
    FILEOUT(){set(7);rep(i,pw[0]=1,9)pw[i]=pw[i-1]*10;}~FILEOUT(){flush();}
    inline void flush(){fwrite(quq,1,O,stdout),fflush(stdout),O=0;}
    inline FILEOUT&operator<<(char c){return quq[O++]=c,*this;}inline FILEOUT&operator<<(string str){if(O>LIMIT)flush();for(char c:str)quq[O++]=c;return*this;}
    inline FILEOUT&operator<<(char*str){if(O>LIMIT)flush();char*cur=str;while(*cur)quq[O++]=(*cur++);return*this;}
    Tp<class T>void write(T x){if(O>LIMIT)flush();if(x<0){quq[O++]=45;x=-x;}do{ST[++sz]=x%10^48;x/=10;}while(x);while(sz)quq[O++]=ST[sz--];}
    inline FILEOUT&operator<<(int x){return write(x),*this;}inline FILEOUT&operator<<(ll x){return write(x),*this;}inline FILEOUT&operator<<(uint x){return write(x),*this;}inline FILEOUT&operator<<(ull x){return write(x),*this;}
    int len,lft,rig;void set(int l){len=l;}inline FILEOUT&operator<<(double x){bool f=x<0;x=f?-x:x,lft=x,rig=1.*(x-lft)*pw[len];return write(f?-lft:lft),quq[O++]='.',write(rig),*this;}
    }out;
    #define int long long
    struct Math{
    vector<int>fac,inv;int mod;
    void set(int n,int Mod){fac.resize(n+1),inv.resize(n+1),mod=Mod;rep(i,fac[0]=1,n)fac[i]=fac[i-1]*i%mod;inv[n]=qpow(fac[n],mod-2);Rep(i,n-1,0)inv[i]=inv[i+1]*(i+1)%mod;}
    int qpow(int x,int y){int ans=1;for(;y;y>>=1,x=x*x%mod)if(y&1)ans=ans*x%mod;return ans;}int C(int n,int m){if(n<0||m<0||n<m)return 0;return fac[n]*inv[m]%mod*inv[n-m]%mod;}
    int gcd(int x,int y){return!y?x:gcd(y,x%y);}int lcm(int x,int y){return x*y/gcd(x,y);}
    }math;
    // clang-format on
    
    const int maxn = 1e3 + 31;
    const int maxm = 4e5 + 54;
    char t[maxn];
    char s[maxm];
    int ans = -1e18;
    struct acautomaton {
      int cnt;
      int ch[maxn][14], fail[maxn], ed[maxn];
      acautomaton() { cnt = 1; }
    
      void ins(char* s, int val) {
        char* cur = s;
        int p = 1;
        while (*cur) {
          int c = (*cur++) - 'a';
          if (!ch[p][c]) ch[p][c] = ++cnt;
          p = ch[p][c];
        }
        ed[p] += val;
      }
    
      void build() {
        queue<int> q;
        rep(i, 0, 13) if (ch[1][i]) fail[ch[1][i]] = 1, q.push(ch[1][i]);
        else ch[1][i] = 1;
        while (q.size()) {
          int u = q.front();
          q.pop();
          rep(i, 0, 13) {
            if (ch[u][i]) {
              fail[ch[u][i]] = ch[fail[u]][i];
              ed[ch[u][i]] += ed[fail[ch[u][i]]];
              q.push(ch[u][i]);
            } else {
              ch[u][i] = ch[fail[u]][i];
            }
          }
        }
      }
    
      int pos[16], tot = 0;
      int nxt[maxn][16], sum[maxn][16];
      int dp[maxn][1 << 14 | 233];
    
      void solve(char* s) {
        int len = strlen(s);
        for (int i = 0; i < len; i++)
          if (s[i] == '?') pos[++tot] = i;
        pos[0] = -1;
        pos[tot + 1] = len;
        rep(i, 0, tot) {
          rep(j, 1, cnt) {
            int p = j;
            rep(k, pos[i] + 1, pos[i + 1] - 1) {
              p = ch[p][s[k] - 'a'];
              sum[j][i] += ed[p];
            }
            nxt[j][i] = p;
          }
        }
    
        rep(i, 1, cnt) rep(j, 0, (1 << 14)) dp[i][j] = -1e18;
        dp[nxt[1][0]][0] = sum[1][0];
    
        auto count = [&](int x) {
          int c = 0;
          while (x) x ^= x & -x, c++;
          return c;
        };
    
        rep(i, 0, (1 << 14) - 1) {
          int v = count(i);
          if (v >= tot) continue;
          rep(j, 1, cnt) {
            rep(k, 0, 13) {
              if (i & (1 << k)) continue;
              cmax(dp[nxt[ch[j][k]][v + 1]][i ^ (1 << k)], dp[j][i] + sum[ch[j][k]][v + 1] + ed[ch[j][k]]);
            }
          }
        }
    
        rep(i, 0, (1 << 14) - 1) {
          if (count(i) ^ tot) continue;
          rep(j, 1, cnt) cmax(ans, dp[j][i]);
        }
      }
    } acam;
    
    signed main() {
      // code begin.
      int _;
      in >> _;
      while (_--) {
        int val;
        in >> t >> val, acam.ins(t, val);
      }
      acam.build(), in >> s, acam.solve(s);
      out << ans << '
    ';
      return 0;
      // code end.
    }
    
  • 相关阅读:
    转: CEF嵌入到单文档mfc
    浅谈C++多态性
    C++面试整理1
    面试汇总
    【转】一些经典的笔试题
    C# 委托
    搭建Nuget
    thinkphp框架之模型(数据库查询)
    利用csc.exe 手动编译C#程序
    css
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12568773.html
Copyright © 2011-2022 走看看