zoukankan      html  css  js  c++  java
  • JZOJ4649. 【NOIP2016提高A组模拟7.17】项链

    Description

    • 现给出n个字符串,总长不超过200,每个字符串有一个权值v[i].
    • 构造一个长度为m(m<=1e14)的字符串,其中每出现一个给定字符串有v[i]的贡献。
    • 问最大贡献是多少。

    Solution

    • 看到m那么大,第一眼就是矩乘。
    • 然后可以发现,如果我们构造一个AC自动机,那么就变成了AC自动机上的DP问题,从一个点转移到可以到的另一个点,就相当于在答案串中加对应的字符。最后只需要转移m步即可得到答案。
    • 一次x转移到y的贡献就是y的fail链上的代表的给定串的权值和。
    • 用矩乘(倍增)优化这个DP就好了。
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define ll long long 
    #define maxn 205
    using namespace std;
    
    const ll inf=-1e15;
    
    int n,i,j,k,len[maxn],s[maxn][maxn];
    char ch;
    int x,y,tot,t,w,d[maxn],to[maxn][26],fail[maxn]; 
    ll m,ans,a[maxn],v[maxn],g[maxn][maxn],f[maxn][maxn],ff[maxn][maxn];
    
    void build(){
    	tot=1;
    	for(i=1;i<=n;i++) {
    		for(x=1,j=1;j<=len[i];j++) {
    			y=s[i][j];
    			if (!to[x][y]) to[x][y]=++tot;
    			x=to[x][y];
    		}
    		v[x]+=a[i];
    	}
    	
    	
    	fail[1]=1,t=w=0;
    	for(i=0;i<26;i++) if (!to[1][i])
    		to[1][i]=1; else y=to[1][i],fail[y]=1,d[++w]=y;
    		
    	while (t<w){
    		x=d[++t];
    		for(i=0;i<26;i++) if (!to[x][i]) to[x][i]=to[fail[x]][i];
    		else {
    			y=to[x][i],fail[y]=to[fail[x]][i];
    			v[y]+=v[fail[y]],d[++w]=y;
    		}
    	}
    }
    
    int main(){
    	freopen("ceshi.in","r",stdin);
    	scanf("%d%lld",&n,&m);
    	for(i=1;i<=n;i++) scanf("%lld",&a[i]);
    	for(i=1;i<=n;i++) {
    		for(ch=getchar();ch<'a'||ch>'z';ch=getchar());
    		for(;ch>='a'&&ch<='z';ch=getchar())
    			s[i][++len[i]]=ch-'a';
    	}
    	
    	build();
    	for(i=1;i<=tot;i++) for(j=1;j<=tot;j++) f[i][j]=g[i][j]=inf;
    	for(i=1;i<=tot;i++) for(j=0;j<26;j++) if (to[i][j]&&to[i][j]!=1)
    		g[i][to[i][j]]=v[to[i][j]];
    	for(i=1;i<=tot;i++) f[i][i]=0;
    	
    	for(;m;m/=2) {
    		if (m&1){
    			for(i=1;i<=tot;i++) for(j=1;j<=tot;j++) ff[i][j]=inf;
    			for(i=1;i<=tot;i++) for(j=1;j<=tot;j++) for(k=1;k<=tot;k++) 	
    				ff[i][k]=max(ff[i][k],f[i][j]+g[j][k]);
    			memcpy(f,ff,sizeof(ff));
    		}
    		for(i=1;i<=tot;i++) for(j=1;j<=tot;j++) ff[i][j]=inf;
    		for(i=1;i<=tot;i++) for(j=1;j<=tot;j++) for(k=1;k<=tot;k++)
    			ff[i][k]=max(ff[i][k],g[i][j]+g[j][k]);
    		memcpy(g,ff,sizeof(ff));
    	}
    	ans=0;
    	for(i=1;i<=tot;i++) ans=max(ans,f[1][i]);
    	printf("%lld",ans);
    }
    
  • 相关阅读:
    使用VSCode创建简单的Razor Webapp--1.入门
    ASP.NET Razor 常用示例
    ASP.NET Razor 语法
    ASP.NET Razor简介
    EF CodeFirst 一对一、一对多、多对多关系
    mysql外键
    EF CodeFirst 之 Fluent API
    替换JDK 对eclipse的影响?
    mysql数据库,安装 !创建!...详解!
    Apache的commons工具类
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/11700945.html
Copyright © 2011-2022 走看看