CF954I Yet Another String Matching Problem
每次操作可以把两个字符串中所有同一种字符变成另外一种
定义两个长度相等的字符串之间的距离为:使两个字符串相等所需要操作的次数的最小值
求 \(s\) 中每一个长度为 \(|t|\) 的连续子串与 \(t\) 的距离
字符集为小写字母 \('a'\) 到 \('f'\)
Sol
考虑如何计算两个等长串的距离
相当于两个匹配的字符之间连边,同一个连通块内可以互相转化,答案就是并查集合并的次数
本题的字符集大小只有 \(6\),那么考虑枚举两种字符匹配连边
匹配就是一个非常套路的反转 \(+\) \(FFT\) 了
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn(1 << 18);
const double pi(acos(-1));
struct Complex {
double a, b;
inline Complex() {
a = b = 0;
}
inline Complex(double _a, double _b) {
a = _a, b = _b;
}
inline Complex operator +(Complex x) const {
return Complex(a + x.a, b + x.b);
}
inline Complex operator -(Complex x) const {
return Complex(a - x.a, b - x.b);
}
inline Complex operator *(Complex x) const {
return Complex(a * x.a - b * x.b, a * x.b + b * x.a);
}
inline Complex Conj() {
return Complex(a, -b);
}
};
Complex a[maxn], b[maxn], w[maxn];
int r[maxn], l, deg, g[maxn], h[maxn], cnt[maxn];
inline void FFT(Complex *p, int opt) {
register int i, j, k, t;
register Complex wn, x, y;
for (i = 0; i < deg; ++i) if (r[i] < i) swap(p[r[i]], p[i]);
for (i = 1; i < deg; i <<= 1)
for(t = i << 1, j = 0; j < deg; j += t)
for (k = 0; k < i; ++k) {
wn = w[deg / i * k];
if (opt == -1) wn.b *= -1;
x = p[j + k], y = wn * p[i + j + k];
p[j + k] = x + y, p[i + j + k] = x - y;
}
}
inline void Init(int n) {
register int i;
for (deg = 1, l = 0; deg < n; deg <<= 1) ++l;
for (i = 0; i < deg; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
for (i = 0; i < deg; ++i) w[i] = Complex(cos(pi * i / deg), sin(pi * i / deg));
}
inline void Mul(int *p, int *q, int *f) {
register int i, k;
register Complex ca, da, db;
for (i = 0; i < deg; ++i) a[i] = Complex(p[i], q[i]);
for (FFT(a, 1), i = 0; i < deg; ++i) {
k = (deg - i) & (deg - 1), ca = a[k].Conj();
b[i] = (ca + a[i]) * (a[i] - ca) * Complex(0, -0.25);
}
for (FFT(b, -1), i = 0; i < deg; ++i) f[i] = (int)(b[i].a / deg + 0.5);
}
int n, m, mp[7][7][maxn], fa[7], ans;
char s[maxn], t[maxn];
inline int Find(int x) {
return fa[x] == x ? x : fa[x] = Find(fa[x]);
}
int main() {
register int i, j, k, d;
scanf(" %s %s", s + 1, t + 1), n = strlen(s + 1), m = strlen(t + 1);
reverse(t + 1, t + m + 1), Init(n + m + 1), d = n - m + 1;
for (i = 1; i <= 6; ++i)
for (j = 1; j <= 6; ++j)
if (i != j) {
for (k = 1; k <= n; ++k) g[k] = s[k] - 'a' + 1 == i;
for (k = 1; k <= m; ++k) h[k] = t[k] - 'a' + 1 == j;
for (Mul(g, h, cnt), k = 1; k <= d; ++k) mp[i][j][k] = cnt[m + k] > 0;
}
for (i = 1; i <= d; ++i) {
for (ans = 0, j = 1; j <= 6; ++j) fa[j] = j;
for (j = 1; j <= 6; ++j)
for (k = 1; k <= 6; ++k)
if (mp[j][k][i] && (Find(j) ^ Find(k))) ++ans, fa[Find(j)] = Find(k);
printf("%d ", ans);
}
return 0;
}
CF954I Yet Another String Matching Problem的更多相关文章
- CF954I Yet Another String Matching Problem 并查集、FFT
传送门 题意:给出两个由小写$a$到$f$组成的字符串$S$和$T$($|S| \geq |T|$),给出变换$c1\,c2$表示将两个字符串中所有$c1$字符变为$c2$,求$S$的每一个长度为$T ...
- CF954I Yet Another String Matching Problem(FFT+并查集)
给定两个字符串\(S,T\) 求\(S\)所有长度为\(|T|\)子串与\(T\)的距离 两个等长的串的距离定义为最少的,将某一个字符全部视作另外一个字符的次数. \(|T|<=|S|<= ...
- 【CF954I】Yet Another String Matching Problem(FFT)
[CF954I]Yet Another String Matching Problem(FFT) 题面 给定两个字符串\(S,T\) 求\(S\)所有长度为\(|T|\)的子串与\(T\)的距离 两个 ...
- Educational Codeforces Round 40 I. Yet Another String Matching Problem
http://codeforces.com/contest/954/problem/I 给你两个串s,p,求上一个串的长度为|p|的所有子串和p的差距是多少,两个串的差距就是每次把一个字符变成另一个字 ...
- 954I Yet Another String Matching Problem
传送门 分析 我们先考虑暴力如何计算 对于S的子串SS,如果它有位置i使得SS[i] != T[i]那么我们就将两个字符之间用并查集连边 最后答案很明显就是并查集中所有边的个数 于是我们可以发现对于S ...
- Codeforces 954I Yet Another String Matching Problem(并查集 + FFT)
题目链接 Educational Codeforces Round 40 Problem I 题意 定义两个长度相等的字符串之间的距离为: 把两个字符串中所有同一种字符变成另外一种,使得两个 ...
- Codeforces.954I.Yet Another String Matching Problem(FFT)
题目链接 \(Description\) 对于两个串\(a,b\),每次你可以选择一种字符,将它在两个串中全部变为另一种字符. 定义\(dis(a,b)\)为使得\(a,b\)相等所需的最小修改次数. ...
- string matching(拓展KMP)
Problem Description String matching is a common type of problem in computer science. One string matc ...
- NYOJ之Binary String Matching
Binary String Matching 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 Given two strings A and B, whose a ...
随机推荐
- trunc 函数用法
转载至:http://blog.csdn.net/aqszhuaihuai/article/details/6303686 1.trunc用于日期,可精确到年,月和日. select trunc(sy ...
- linux下启动tomcat服务的命令是什么
Linux下tomcat服务的启动.关闭与错误跟踪,使用PuTTy远程连接到服务器以后,通常通过以下几种方式启动关闭tomcat服务:切换到tomcat主目录下的bin目录(cd usr/local/ ...
- 介绍&代码
之前参考前辈实现的分页组件,还ok. 介绍: 基于Web,实现分页样式 和 控制页面内容数据的展示形式. 实现: from django.utils.safestring import mark_sa ...
- solr 服务搭建
1. linux 中 安装jdk, tomcat, 2. 下载 solr-4.10.3.tgz.tgz 并解压 解压后文件夹:solr-4.10.3 3. 将 solr-4.10.3/dist 下 ...
- Mac下Homebrew的图形化界面工具Cakebrew
安装: brew cask install cakebrew 如果不能下载直接上官网下载dmg包进行安装. 参考: https://www.cakebrew.com/ https://github.c ...
- [Xamarin.Android] 如何使用Google Map V2 (转帖)
Google Map v1已經在2013年的3月開始停止支援了,目前若要在你的Android手機上使用到Google Map,就必須要使用 到Google Map v2的版本.在Xamarin要使用G ...
- Jexus高级功能设置
我们对服务器软件Jexus作了简单的介绍,同时我们也对Jexus的整体配置作了详细的讲解,介绍了Jexus的进程守护工具"jws.guard",相信各位读者对于Jexus应该已经有 ...
- net与树莓派的情缘-安装Redis(四)
在Linux下安装Redis非常简单,具体步骤如下(官网有说明): .下载源码,解压缩后编译源码. $ wget http://download.redis.io/releases/redis-3.0 ...
- Python爬虫学习:一些关于爬虫的知识的充电
什么是Http和Https http协议:全称是HyperText Transfer Protocol,中文意思是超文本传输协议,是一种发布和接收Html页面的方法.默认的端口号是80 https协议 ...
- Android多媒体技术之视频播放
1.Android中视频播放方式 surfaceView+MediaPlayer,通过MediaPlayer来控制视频的播放.暂停.进度等: 使用VideoView 来播放,这个类其实也是继承了Sur ...