zoukankan      html  css  js  c++  java
  • [Codeforces 696D] Legen...

      题目大意:

        给出一些匹配串,要造一个长度不超过L的字符串,每个匹配串有自己的价值,匹配串每次出现在字符串里都会贡献一次价值...要求可能得到的最大价值。

        匹配串总长不超200,L<=10^14,时限6s

      典型的倍增floyd...看数据范围大概就知道是什么东西了= =

      暴力写法的话..建个AC自动机,每个节点的价值,就是结束节点在它的fail链上的匹配串的价值总和。。 然后在上面暴力DP。f[i][j]表示从i节点开始,往后走j步能得到的最大价值。

      这个形式和USACO那道“奶牛接力跑‘一模一样。。。

      f[i][j][k]表示从i节点开始,走2^j步,到达k的最大价值。fa[i][j][k]:从k节点开始,走2^j步,能否到达i。

      f[i][j][k]=max{ f[i][j-1][k1]+f[k1][j-1][k] },( fa[k1][j-1][i]和fa[k][j-1][k1]为true

      求出f后,就和快速幂的姿势一样把L拆成若干个二的次幂之和,然后把对应的各个f数组并起来(记为g)。

      最后的答案就是max{ g[0][i] },(i为自动机上的节点。

      时间复杂度O(n^3*logL)..CF测评姬挺快的。。只跑了1200+ms。。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<bitset>
      6 #define ll long long
      7 #define ull unsigned long long
      8 #define d double
      9 using namespace std;
     10 const int maxn=203;
     11 const ll inf=(1ll<<62)-1ll;
     12 int ch[maxn][26],next[maxn][26],tot;
     13 int dl[maxn],fail[maxn],val[maxn],v[maxn];
     14 ll f[maxn][61][maxn],g[maxn][2][maxn];
     15 bitset<maxn>fa[maxn][61];
     16 char s[maxn];
     17 
     18 int i,j,k,n,m,now,pre;
     19 ll L;
     20 bool first=1;
     21 
     22 
     23 int ra,fh;char rx;
     24 inline int read(){
     25     rx=getchar(),ra=0,fh=1;
     26     while(rx!='-'&&(rx<'0'||rx>'9'))rx=getchar();
     27     if(rx=='-')fh=-1,rx=getchar();
     28     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
     29 }
     30 inline void upd(ll &a,ll b){if(a<b)a=b;}
     31 
     32 void trie(int n,int v){
     33     int p=0;
     34     for(int i=1;i<=n;i++){
     35         s[i]-='a';
     36         if(!ch[p][s[i]])ch[p][s[i]]=++tot,p=tot;
     37         else p=ch[p][s[i]];
     38     }
     39     val[p]+=v;//printf("   ggpos:%d
    ",p);
     40 }
     41 void getfail(){
     42     int l=0,r=1,i,now,j,p;dl[1]=0;
     43     while(l<r){
     44         now=dl[++l];
     45         for(i=0;i<26;i++)if(ch[now][i]){
     46             j=ch[now][i],dl[++r]=j,next[now][i]=j;
     47             for(p=fail[now];p&&!ch[p][i];p=fail[p]);
     48             if(!now)fail[j]=0;else fail[j]=ch[p][i];
     49             val[j]+=val[fail[j]];//printf("   %d - - - ->%d   val:%d
    ",j,fail[j],val[j]);
     50         }else{
     51             for(p=fail[now];p&&!ch[p][i];p=fail[p]);
     52             next[now][i]=ch[p][i];
     53         }
     54     }
     55 }
     56 
     57 inline void run_fa(int j){
     58     int i,k1;//printf("j:%d
    ",j);
     59     for(i=0;i<=tot;i++)for(k1=0;k1<=tot;k1++)
     60         if(fa[i][j-1][k1])fa[i][j]|=fa[k1][j-1];
     61 //    for(i=0;i<=tot;i++)for(k1=0;k1<=tot;k1++)if(fa[i][j][k1])printf("  %d->%d
    ",k1,i);
     62 }
     63 inline void run_f(int j){
     64     int i,k;register int k1;//printf("j:%d
    ",j);
     65     for(i=0;i<=tot;i++)for(k=0;k<=tot;k++)if(fa[k][j][i]){
     66         for(k1=0;k1<=tot;k1++)if(fa[k1][j-1][i]&&fa[k][j-1][k1])
     67             upd(f[i][j][k],f[i][j-1][k1]+f[k1][j-1][k]);//,printf("    %d-->%d-->%d
    ",i,k1,k);
     68     }else f[i][j][k]=-inf;
     69 }
     70 inline void run_merge(int j){
     71     int i,k;register int k1;
     72     if(first){
     73         first=0;
     74         for(i=0;i<=tot;i++)for(k=0;k<=tot;k++)g[i][now][k]=f[i][j-1][k];
     75         return;
     76     }
     77     for(i=0;i<=tot;i++)for(k=0;k<=tot;k++)
     78         for(g[i][now][k]=-inf,k1=0;k1<=tot;k1++)if(fa[k][j-1][k1])
     79             upd(g[i][now][k],g[i][pre][k1]+f[k1][j-1][k]);
     80 }
     81 
     82 
     83 
     84 int main(){
     85     n=read(),scanf("%I64d",&L);
     86     for(i=1;i<=n;i++)v[i]=read();
     87     for(i=1;i<=n;i++)scanf("%s",s+1),trie(strlen(s+1),v[i]);
     88     getfail();
     89     
     90     int a=0;
     91     for(i=0;i<=tot;i++)for(k=0;k<=tot;k++)f[i][0][k]=-inf;
     92     for(i=0;i<=tot;i++)for(j=0;j<26;j++)fa[next[i][j]][0][i]=1,f[i][0][next[i][j]]=val[next[i][j]];
     93     
     94 //    for(i=0;i<=tot;i++)for(int k1=0;k1<=tot;k1++)if(fa[i][0][k1])printf("  %d->%d
    ",k1,i);
     95     
     96     now=1,pre=0;
     97     while(L){
     98         a++;
     99         if(L&1)run_merge(a),swap(now,pre);
    100         L>>=1;
    101         if(!L)break;
    102         run_fa(a),run_f(a);
    103     }
    104     ll ans=0;
    105     for(i=0;i<=tot;i++)upd(ans,g[0][pre][i]);
    106     printf("%I64d
    ",ans);
    107 }
    View Code

    比赛的时候这道题肝了整整1h。。。最后1min才过的样例..竟然就过掉了

  • 相关阅读:
    一、ThinkPHP的介绍
    一、ThinkPHP的介绍
    perl 爬虫两个技巧
    perl 爬虫两个技巧
    perl 爬取上市公司业绩预告
    perl lwp get uft-8和gbk
    perl lwp get uft-8和gbk
    perl 爬取同花顺数据
    perl 爬取同花顺数据
    php 接口示例
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5673054.html
Copyright © 2011-2022 走看看