LINK


简要题意

给你一个串s,上面有字母和一些通配符,问你将通配符换成字母之后最多可以出现多少次串t


首先有一个很傻子的做法就是\(dp_{i,j}\)表示s到第i个位置匹配t串前j个字符的完整t串个数

然后每次枚举前缀看看能不能转移。。。太不优秀了

那么就考虑这样做:

\(dp_{i}\)表示最后一个出现的完整的串t在第i个位置结尾的最大出现次数

\(maxv_{i}\)表示最后一个出现的完整的串t在第i个位置前结尾的最大出现次数

首先有一个转移是,如果当前位置被匹配,那么\(dp_{i} = maxv_{i - lent} + 1\)

或者我们就需要枚举当前串和上一个的公共长度

这样就相当于枚举t的一个是前缀又是后缀的东西

就很容易想到跳fail

然后就加上一个kmp板子就可以了

复杂度是\(|s|*|t|\)的


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 1e5 + 10;
char s[N], t[N];
int fail[N], dp[N], maxv[N];
void getfail(char *s) {
int lens = strlen(s + 1);
int j = 0; fail[1] = 0;
fu(i, 2, lens) {
while (j && s[j + 1] != s[i]) j = fail[j];
if (s[j + 1] == s[i]) ++j;
fail[i] = j;
}
}
bool match(char *s, int pos, char *t, int len) {
fu(i, 1, len)
if (s[pos + i -1] != t[i] && s[pos + i - 1] != '?') return 0;
return 1;
}
int main() {
#ifdef dream_maker
freopen("input.txt", "r", stdin);
#endif
scanf("%s%s", s + 1, t + 1);
getfail(t);
int lens = strlen(s + 1), lent = strlen(t + 1);
fu(i, lent, lens) {
if (match(s, i - lent + 1, t, lent)) {
dp[i] = max(dp[i], maxv[i - lent] + 1);
int j = fail[lent];
while (j) {
dp[i] = max(dp[i], dp[i - (lent - j)] + 1);
j = fail[j];
}
maxv[i] = max(maxv[i], dp[i]);
}
maxv[i] = max(maxv[i], maxv[i - 1]);
}
Write(maxv[lens]);
return 0;
}

最新文章

  1. [Android] Visual Studio Emulator For Android 相关
  2. CSS 选择器【详解】
  3. mac安装Mysql官方示例数据库employee
  4. Android Activity的启动过程
  5. Kinetic使用注意点--layer
  6. ThinkPHP 常用配置项列表
  7. sql2008r2局域网复制订阅实操
  8. 使用boost中的property_tree实现配置文件
  9. yii2之数据验证
  10. CSS实现商城分类导航效果(hover选择器)
  11. Echarts关于仪表盘
  12. el-table表格标题换行
  13. Codeforces Round #319 (Div. 2) D - Invariance of Tree
  14. GUI保存打开对话框
  15. linux ubuntu设置root用户初始密码
  16. 在 Ubuntu 16.04上安装 vsFTPd
  17. flask_admin 笔记五 内置模板设置
  18. centos6.5环境DNS-本地DNS主从服务器bind的搭建
  19. new 关键字
  20. 安装nvm之后node不可用,“node”不是内部或外部命令,也不是可运行的程序或批处理文件(ng)

热门文章

  1. spring-boot 加入拦截器Interceptor
  2. scp 上传 下载 文件
  3. Sql Server中的DBCC命令详细介绍
  4. 欢迎来到 Flask 的世界
  5. slim(4621✨)
  6. 大小堆C++实现
  7. torch7框架 深度学习(1)
  8. UVALive-3211 Now or later (2-SAT+二分)
  9. 进程上下文频繁切换导致load average过高
  10. Pandas 时间序列数据绘制X轴主要刻度和次要刻度