用 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. luogu P3601 签到题

    链接P3601 签到题 求\[\sum_{i=l}^{r} i-\phi_i\] \(l,r\leq 10^{12},\ r-l\leq 10^6\) 杜教筛似乎做不了. 然后再看\(l\),\(r\ ...

  2. bzoj3091 城市旅行 LCT + 区间合并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3091 题解 调了整个晚自习才调出来的问题. 乍一看是个 LCT 板子题. 再看一眼还是个 LC ...

  3. java:Set对象TreeSet有序子类,HashSet无序子类,重复对象二

    TreeSet有序子类; HashSet无序子类 重复重复元素,Object对象是通过equals和hashCode来进行过滤的. 如果将上一篇提到中的例子中的TreeSet,换成HashSet,那么 ...

  4. for-in语句和with语句、break和continue语句

    for-in语句 for-in语句是一种精准迭代语句,可以用来枚举对象的属性,用以遍历一个对象的全部属性. for…in声明用于对数组或者对象的属性进行循环操作: for…in循环中的代码每执行一次, ...

  5. oracle java for ubuntu apt-get

    oracle java PPA: ppa:webupd8team/javathe key word use for search more infomation: webupd8team

  6. React使用的思考总结

    1.事件处理中的this指针问题 在 react 中,用 class 声明一个组件,调用 class 中的方法时,如果该方法中有 this 且没有手动绑定 this 指针,则会发生 this 指向 u ...

  7. codeforces D Salary Changing

    题意:给你n个人,和s块钱,每个人都有一个工资区间,你给所有人都发工资.然后要他们工资的中位数最大. 思路:二分找那个值.那个值要满足至少有n/2+1个工资区间内. #include<cstdi ...

  8. synchronized 同步

    1.synchronized关键字的作用域有二种: 1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有 ...

  9. 【ArchSummit干货分享】个推大数据金融风控算法实践

    作者:个推高级数据工程师 晓骏 众所周知,金融是数据化程度最高的行业之一,也是人工智能和大数据技术重要的应用领域.随着大数据收集.存储.分析和模型技术日益成熟,大数据技术逐渐应用到金融风控的各个环节. ...

  10. 关于openGL、GPUImage、ios直播相关不错的博客

    http://www.jianshu.com/users/815d10a4bdce/latest_articles