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

    Description

    每个字符串有些价值,问生成长度为 (l) 的字符串最多能获得多少价值,总字符数不超过 (200), (lleqslant 10^{14}) .

    Sol

    AC自动机 + 倍增Floyd.

    用AC自动机统计到达每个节点会获得的权值.

    然后在AC自动机从根节点开始找一条最长路,就用Floyd倍增就可以了...

    发现自己AC自动机做Fail树的时候写错了,改了好久没改出来,最后发现不能直接将根扔进队列里...应该把根的所有子节点扔进去..

    然后类似快速幂做就可以了.写矩阵的时候需要判断一下能否到达,我用 (-1) 来表示能否到达.

    转移就是 (C[i][j]=max{C[i][j],A[i][k]+B[k][j]},A[i][k]!=-1,B[k][j]!=-1) .

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    const int M = 205;
    const int N = 20050;
    typedef long long LL;
    typedef vector< LL > Vec;
    typedef vector< Vec > Mat;
    
    void F(Mat &A,int v=-1) {
    	int n=A.size();
    	for(int i=0;i<n;i++) for(int j=0;j<n;j++) A[i][j]=v;
    }
    Mat operator * (const Mat &A,const Mat &B) {
    	int n=A.size();Mat C(n,Vec(n));F(C);
    	for(int k=0;k<n;k++) for(int i=0;i<n;i++) for(int j=0;j<n;j++) 
    		if(A[i][k]!=-1 && B[k][j]!=-1) C[i][j]=max(C[i][j],A[i][k]+B[k][j]);
    	return C;
    }
    Mat operator ^ (Mat A,LL b) {
    	int n=A.size();Mat r(n,Vec(n));
    	F(r);for(int i=0;i<n;i++) r[i][i]=0;
    	for(;b;b>>=1,A=A*A) if(b&1) r=r*A;
    	return r;
    }
    void Print(const Mat &A) {
    	int n=A.size();
    	for(int i=0;i<n;i++) {
    		for(int j=0;j<n;j++) cout<<A[i][j]<<" ";
    		cout<<endl;
    	}cout<<"---------------------"<<endl;
    }
    
    struct AC_Auto {
    	int rt,cnt;
    	int f[N],ch[N][26],v[N];
    	
    	int NewNode() { ++cnt;v[cnt]=f[cnt]=0,memset(ch[cnt],0,sizeof(ch[cnt]));return cnt; }
    	void init() { cnt=rt=f[rt]=v[rt]=0;memset(ch[rt],0,sizeof(ch[rt])); }
    	void insert(char *s,int val) {
    		int l=strlen(s),o=rt;
    		for(int i=0;i<l;i++) {
    			if(!ch[o][s[i]-'a']) ch[o][s[i]-'a']=NewNode();
    			o=ch[o][s[i]-'a'];
    		}v[o]+=val;
    	}
    	void getFail() {
    		queue< int > q;
    		for(int i=0;i<26;i++) if(ch[rt][i]) q.push(ch[rt][i]);
    		for(;!q.empty();) {
    			int x=q.front();q.pop();
    			for(int i=0;i<26;i++) {
    				if(!ch[x][i]) ch[x][i]=ch[f[x]][i];
    				else q.push(ch[x][i]),f[ch[x][i]]=ch[f[x]][i],v[ch[x][i]]+=v[f[ch[x][i]]];
    			}
    		}
    //		for(int i=0;i<=cnt;i++) cout<<i<<"-->"<<f[i]<<endl;
    	}
    	void Make(Mat &A) {
    		A.resize(cnt+1,Vec(cnt+1));
    		int n=A.size();F(A);
    		for(int i=0;i<n;i++) for(int j=0;j<26;j++) A[i][ch[i][j]]=v[ch[i][j]],A[i][ch[rt][j]]=v[ch[rt][j]];
    	}
    }ac;
    
    LL n,l,ans;
    LL a[N];
    char s[N];
    
    int main() {
    //	freopen("in.in","r",stdin);
    	
    	ios::sync_with_stdio(false);
    	ac.init();
    	
    	cin>>n>>l;
    	for(int i=1;i<=n;i++) cin>>a[i];
    	for(int i=1;i<=n;i++) cin>>s,ac.insert(s,a[i]);
    	
    	ac.getFail();
    	Mat r;
    	ac.Make(r);
    	
    //	Print(r);
    	r=r^l;
    	
    	for(int i=0;i<(int)r.size();i++) ans=max(ans,r[0][i]);
    	
    	cout<<ans<<endl;
    	return 0;
    }
    

      

  • 相关阅读:
    Neoj4安装使用教程
    毕业设计每日博客——第五周3
    毕业设计每日博客——第五周2
    不知道为什么,我就是被这个冒号迷惑了
    对items函数的理解
    关于运算符+的一点想法
    请使用迭代查找一个list中最小和最大值,并返回一个tuple
    Python中最常见括号()、[]、{}的区别
    ping和telnet的区别
    SQL注入原理
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/6165747.html
Copyright © 2011-2022 走看看