Codeforces 1163D Mysterious Code(AC自动机+DP)
用 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)的更多相关文章
- Codeforces 1015F Bracket Substring AC自动机 + dp
Bracket Substring 这么垃圾的题怎么以前都不会写啊, 现在一眼怎么就会啊.... 考虑dp[ i ][ j ][ k ][ op ] 表示 已经填了 i 个空格, 末尾串匹配到 所给串 ...
- 【hdu2457】ac自动机 + dp
传送门 题目大意: 给你一个字符主串和很多病毒串,要求更改最少的字符使得没有一个病毒串是主串的子串. 题解: ac自动机 + dp,用病毒串建好ac自动机,有毒的末尾flag置为true 构建fail ...
- POJ1625 Censored!(AC自动机+DP)
题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...
- HDU2296 Ring(AC自动机+DP)
题目是给几个带有价值的单词.而一个字符串的价值是 各单词在它里面出现次数*单词价值 的和,问长度不超过n的最大价值的字符串是什么? 依然是入门的AC自动机+DP题..不一样的是这题要输出具体方案,加个 ...
- HDU2457 DNA repair(AC自动机+DP)
题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步) ...
- hdu 4117 GRE Words AC自动机DP
题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...
- hdu 2457(ac自动机+dp)
题意:容易理解... 分析:这是一道比较简单的ac自动机+dp的题了,直接上代码. 代码实现: #include<stdio.h> #include<string.h> #in ...
- HDU 2425 DNA repair (AC自动机+DP)
DNA repair Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU2296——Ring(AC自动机+DP)
题意:输入N代表字符串长度,输入M代表喜欢的词语的个数,接下来是M个词语,然后是M个词语每个的价值.求字符串的最大价值.每个单词的价值就是单价*出现次数.单词可以重叠.如果不止一个答案,选择字典序最小 ...
随机推荐
- 路径path知识点
1. 获取当前文件的路径 test.py os.path.abspath(path) # 返回当前文件运行的绝对路径 print("程序的绝对路径是",os.path.abspat ...
- ubuntu16.04 下安装jdk
1. 在/usr/lib目录下新建jdk mkdir jdk 2. 执行文件移动 sudo mv ./resource/jdk-8u191-linux-x64.tar. ...
- SpringBoot整合AOP
一.创建LogComponent类 类上加上@Component和@Aspect 表示把该类注册成spring组件和aop 二.创建6个方法 2.1 @Poin ...
- Day_04-数组,元组,列表
# for i in range(5): # for j in range(5): # print(i,j) # import re # def rm(): # a = ' 1 2 3 4 5 ' # ...
- 牛客网 珂学送分( 期望DP )
题意 : 题目链接 分析 : 听队友说一般概率从前往后推.期望从后往前推......... #include<bits/stdc++.h> using namespace std; ; d ...
- Ubuntu 16.04下使用docker部署rabbitmq
(以下docker相关的命令,需要在root用户环境下或通过sudo提升权限来进行操作.) 1.拉取rabbimq镜像到本地 docker pull rabbitmq 2. Docker运行rabbi ...
- RAC & MVVM 学习资料整理
最后更新:2017-01-23 参考链接: MVVM奇葩说 MVVM 介绍 Model-View-ViewModel for iOS [译] 唐巧--被误解的 MVC 和被神化的 MVVM React ...
- StringUtils.join()
org.apache.commons.lang.StringUtils; StringUtils.join(null) = null StringUtils.join([]) ...
- mysq访问方式
mysql -h10.81.32.196 -P5152 -Dns_map_data_new -uwangyuchuan_r -p3DLg15rhSsm0O7Nsselect uid,name from ...
- MySQL Schedule Event
建立事件历史日志表-- 用于查看事件执行时间等信息create table t_event_history ( dbname varchar(128) not null default ' ...