用 AC自动机 来做有点想不到,捞一手就是学一手。

设 dp[ i ][ j ] 表示字符串 c 中的第 i 位到字典树上节点 j 的最大值是多少, word[ j ] 表示在节点 j 下对答案修改的值是多少。

首先可以确定是 s 和 t 塞入字典树时,他们的结尾节点的 word 值显然一个是 1 一个是 -1 ,接下来就是 fail 数组上的一波操作,对于当前节点 j ,我们的 word[ j ] 需要加上 word[ fail[ j ] ] ,即当选到当前节点 j 时候,加上可能匹配到的一个完整的 s 或者一个完整的 t 的影响。假设 s = "baaaa" , t = "aa" ,当 j 节点在 s 下的第一个 ‘a' 时, fail[ j ] 在 t 的第一个 ‘a’ , word[ j ] 不进行修改,当 j 节点在 s 下的第二个 'a' 时, fail[ j ] 在 t 的第二个 ‘a' , word[ j ] 更新值为 word[ j ]-1 ,表示在匹配过程中到 s 的 "baa" 时,恰好也匹配到了一个 t ,我们需要减去一个完整的 t 带来答案的影响,同理,到 s 的第三个 ‘a’ 不修改, s 的第四个 'a' 修改为 word[ j ]-1 ,那么word就是这么个作用。

接下来转移方程就比较好理解了,设 id 为在节点 j 下的 ‘a' ~ ‘z’ 的任意一个节点值,显然只有在 c[ i ] 为匹配符或者   c[ i ] 恰好等于节点 j 下对应的字符才能进行转移,那么转移方程就是 dp[ i+1 ][ id ]=max(dp[ i+1 ][ id ],dp[ i ][ j ]+word[ id ]) ,最后只需要枚举在所有节点下的 i 等于 c.size() 的 dp 值取 max 就是答案了。

 //      ——By DD_BOND 

 //#include<bits/stdc++.h>
#include<functional>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<iomanip>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<cstddef>
#include<cstdio>
#include<memory>
#include<vector>
#include<cctype>
#include<string>
#include<cmath>
#include<queue>
#include<deque>
#include<ctime>
#include<stack>
#include<map>
#include<set> #define fi first
#define se second
#define MP make_pair
#define pb push_back
#define INF 0x3f3f3f3f
#define pi 3.1415926535898
#define lowbit(a) (a&(-a))
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define Min(a,b,c) min(a,min(b,c))
#define Max(a,b,c) max(a,max(b,c))
#define debug(x) cerr<<#x<<"="<<x<<"\n"; using namespace std; typedef long long ll;
typedef pair<int,int> P;
typedef pair<ll,ll> Pll;
typedef unsigned long long ull; const ll LLMAX=2e18;
const int MOD=1e9+;
const double eps=1e-;
const int MAXN=1e6+; inline ll sqr(ll x){ return x*x; }
inline int sqr(int x){ return x*x; }
inline double sqr(double x){ return x*x; }
ll gcd(ll a,ll b){ return b==? a: gcd(b,a%b); }
ll exgcd(ll a,ll b,ll &x,ll &y){ ll d; (b==? (x=,y=,d=a): (d=exgcd(b,a%b,y,x),y-=a/b*x)); return d; }
ll qpow(ll a,ll n){ll sum=;while(n){if(n&)sum=sum*a%MOD;a=a*a%MOD;n>>=;}return sum;}
inline int dcmp(double x){ if(fabs(x)<eps) return ; return (x>? : -); } int tree[][],word[],fail[],cnt=,dp[][]; void insert(string s,int v){
int root=;
for(int i=;i<(int)s.size();i++){
int id=s[i]-'a';
if(!tree[root][id]) tree[root][id]=++cnt;
root=tree[root][id];
}
word[root]+=v;
} void get_fail(){
queue<int>q;
for(int i=;i<;i++)
if(tree[][i]){
fail[tree[][i]]=;
q.push(tree[][i]);
}
while(!q.empty()){
int u=q.front(); q.pop();
for(int i=;i<;i++)
if(tree[u][i]){
fail[tree[u][i]]=tree[fail[u]][i];
q.push(tree[u][i]);
}
else tree[u][i]=tree[fail[u]][i];
word[u]+=word[fail[u]];
}
} int main(void)
{
ios::sync_with_stdio(false); cin.tie(); cout.tie();
int ans=-INF; string c,s,t; cin>>c>>s>>t;
insert(s,); insert(t,-); get_fail();
memset(dp,-INF,sizeof(dp));
dp[][]=;
for(int i=;i<(int)c.size();i++)
for(int j=;j<=cnt;j++)
for(int z=;z<;z++)
if(c[i]=='*'||'a'+z==c[i]){
int id=tree[j][z];
dp[i+][id]=max(dp[i+][id],dp[i][j]+word[id]);
}
for(int i=;i<=cnt;i++) ans=max(ans,dp[c.size()][i]);
cout<<ans<<endl;
return ;
}

Codeforces 1163D Mysterious Code(AC自动机+DP)的更多相关文章

  1. Codeforces 1015F Bracket Substring AC自动机 + dp

    Bracket Substring 这么垃圾的题怎么以前都不会写啊, 现在一眼怎么就会啊.... 考虑dp[ i ][ j ][ k ][ op ] 表示 已经填了 i 个空格, 末尾串匹配到 所给串 ...

  2. 【hdu2457】ac自动机 + dp

    传送门 题目大意: 给你一个字符主串和很多病毒串,要求更改最少的字符使得没有一个病毒串是主串的子串. 题解: ac自动机 + dp,用病毒串建好ac自动机,有毒的末尾flag置为true 构建fail ...

  3. POJ1625 Censored!(AC自动机+DP)

    题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...

  4. HDU2296 Ring(AC自动机+DP)

    题目是给几个带有价值的单词.而一个字符串的价值是 各单词在它里面出现次数*单词价值 的和,问长度不超过n的最大价值的字符串是什么? 依然是入门的AC自动机+DP题..不一样的是这题要输出具体方案,加个 ...

  5. HDU2457 DNA repair(AC自动机+DP)

    题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步) ...

  6. hdu 4117 GRE Words AC自动机DP

    题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...

  7. hdu 2457(ac自动机+dp)

    题意:容易理解... 分析:这是一道比较简单的ac自动机+dp的题了,直接上代码. 代码实现: #include<stdio.h> #include<string.h> #in ...

  8. HDU 2425 DNA repair (AC自动机+DP)

    DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. HDU2296——Ring(AC自动机+DP)

    题意:输入N代表字符串长度,输入M代表喜欢的词语的个数,接下来是M个词语,然后是M个词语每个的价值.求字符串的最大价值.每个单词的价值就是单价*出现次数.单词可以重叠.如果不止一个答案,选择字典序最小 ...

随机推荐

  1. CF506E Mr. Kitayuta's Gift

    这道题神仙到让我面临着买不到冰皮月亮蛋糕的风险来写题解 (蛋糕真好吃呜呜呜) 这篇题解参考了CQzhangyu神仙的做法. (目测比标程科学好写) 限制是要回文,根据我们做字符串计数的常识,一定是尽量 ...

  2. getopt:命令行选项、参数处理

    在写shell脚本时经常会用到命令行选项.参数处理方式,如: ./test.sh -f config.conf -v --prefix=/home -f 为短选项,它需要一个参数,即config.co ...

  3. mysql CREATE DATABASE语句 语法

    mysql CREATE DATABASE语句 语法 作用:创建数据库. 大理石构件 语法:CREATE DATABASE database_name mysql CREATE DATABASE语句 ...

  4. web上传大文件(>4G)有什么解决方案?

    众所皆知,web上传大文件,一直是一个痛.上传文件大小限制,页面响应时间超时.这些都是web开发所必须直面的. 本文给出的解决方案是:前端实现数据流分片长传,后面接收完毕后合并文件的思路. 实现文件夹 ...

  5. codeforces 868C - Qualification Rounds(构造)

    原题链接:http://codeforces.com/problemset/problem/868/C 题意:有k个队伍参加比赛,比赛有n个预选的题目,有些队伍对已经事先知道了一些题目.问能不能选出若 ...

  6. 一台电脑多个git使用 push 时候出现denied

    http://my.oschina.net/silentboy/blog/220158 当一台电脑上多个git account 的时候, 出现如下问题, $ git push origin maste ...

  7. kubernetes-traefik(二十一)

    参考文档:http://traefik.cn/ traefik和ingress的对比 ingress: 使用nginx作为前端负载均衡,通过ingress controller不断的和kubernet ...

  8. 2009年4月,Twitter宣布他们已经把大部分后端程序从Ruby迁移到Scala

    w Scala 简介 | 菜鸟教程  http://www.runoob.com/scala/scala-intro.html

  9. DelayQueue 源码分析

    DelayQueue DelayQueue 是基于 PriorityQueue 实现的线程安全的无界优先级阻塞队列, 队列的头部元素必须在超时后才能移除,元素必须实现 Delayed 接口. 创建实例 ...

  10. 使用GOGS搭建自己的Git托管

    大家在开发中一般使用的git服务都是公司搭建好的,或者就是直接用gayhub提供的免费的仓库 如果想搭建一个自己的仓库的话怎么弄,这里给大家安利一款开箱即用的git托管服务:gogs. gogs是基于 ...