[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才过的样例..竟然就过掉了

原文地址:https://www.cnblogs.com/czllgzmzl/p/5673054.html