题目链接:MAXMATCH - Maximum Self-Matching

Description

You're given a string s consisting of letters 'a', 'b' and 'c'.

The matching function \(m_s( i )\) is defined as the number of matching characters of s and its i-shift. In other words, \(m_s( i )\) is the number of characters that are matched when you align the 0-th character of s with the i-th character of its copy.

You are asked to compute the maximum of \(m_s( i )\) for all i ( 1 <= i <= |s| ). To make it a bit harder, you should also output all the optimal i's in increasing order.

Input

The first and only line of input contains the string s. \(2 \le |s| \le 10^5\).

Output

The first line of output contains the maximal \(m_s( i )\) over all i.

The second line of output contains all the i's for which \(m_s( i )\) reaches maximum.

Example

Input:
caccacaa Output:
4
3 Explanation: caccacaa
caccacaa The bold characters indicate the ones that match when shift = 3.

Solution

题意

给定一个字符串 \(s\) (下标从 \(0\) 开始,只包含 'a', 'b', 'c'),让 \(s\) 与 \(s\) 匹配,下标从 \(1\) 移动到 \(|s|\),每次匹配时的相同的字符个数记为 \(m_s( i )\),求 \(m_s( i )\) 的最大值,以及最大值所匹配的所有位置。

比如 ababa

ababa
ababa
ababa
ababa
ababa

\(m_s( i )\) 分别为 \(0, 3, 0, 1\),最大值为 \(3\)。

思路

FFT

字符串匹配问题。

设模式串为 \(p\),目标串为 \(t\),\(f[k]\) 为模式串从目标串第 \(k\) 位开始匹配的结果。

对 \(a\),\(b\),\(c\) 分开求。

首先判断 \(a\) 的情况,将字符串转化为 01 串,比如 ababa 转为 10101。

那么

\[f[k] = \sum_{i=0}^{|s|-k-1} p[i] \cdot t[k + i]
\]

\[f[k] = \sum_{i=k}^{|s|-1} p[i - k] \cdot t[i]
\]

将模式串倒置,有

\[f[k] = \sum_{i=k}^{|s|-1} p[|s| - 1 - i + k] \cdot t[i]
\]

令 \(j = |s| - 1 - i + k\),有

\[f[k] = \sum_{i+j=|s|-1+k} p[j] \cdot t[i]
\]

用 \(FFT\) 求一下卷积即可。

对于 \(b\) 和 \(c\) 的求法相同。

Code

#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1);
const double eps = 1e-8;
typedef complex<double> Complex;
const int maxn = 2e6 + 10; Complex p[maxn], t[maxn];
Complex a[maxn], b[maxn], c[maxn];
int ans[maxn];
string str;
int n;
int bit = 2, rev[maxn]; void get_rev(){
memset(rev, 0, sizeof(rev));
while(bit <= n + n) bit <<= 1;
for(int i = 0; i < bit; ++i) {
rev[i] = (rev[i >> 1] >> 1) | (bit >> 1) * (i & 1);
}
} void FFT(Complex *arr, int op) {
for(int i = 0; i < bit; ++i) {
if(i < rev[i]) swap(arr[i], arr[rev[i]]);
}
for(int mid = 1; mid < bit; mid <<= 1) {
Complex wn = Complex(cos(PI / mid), op * sin(PI / mid));
for(int j = 0; j < bit; j += mid<<1) {
Complex w(1, 0);
for(int k = 0; k < mid; ++k, w = w * wn) {
Complex x = arr[j + k], y = w * arr[j + k + mid];
arr[j + k] = x + y, arr[j + k + mid] = x - y;
}
}
}
} int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> str;
n = str.size();
for(int i = 0; i < n; ++i) {
p[n - i - 1] = str[i] == 'a' ? 1 : 0;
t[i] = p[n - i - 1];
}
get_rev();
FFT(p, 1); FFT(t, 1);
for(int i = 0; i < bit; ++i) {
a[i] = p[i] * t[i];
}
FFT(a, -1); for(int i = 0; i < n; ++i) {
p[n - i - 1] = str[i] == 'b' ? 1 : 0;
t[i] = p[n - i - 1];
}
for(int i = n; i < bit; ++i) {
p[i] = 0;
t[i] = 0;
}
FFT(p, 1); FFT(t, 1);
for(int i = 0; i < bit; ++i) {
b[i] = p[i] * t[i];
}
FFT(b, -1); for(int i = 0; i < n; ++i) {
p[n - i - 1] = str[i] == 'c' ? 1 : 0;
t[i] = p[n - i - 1];
}
for(int i = n; i < bit; ++i) {
p[i] = 0;
t[i] = 0;
}
FFT(p, 1); FFT(t, 1);
for(int i = 0; i < bit; ++i) {
c[i] = p[i] * t[i];
}
FFT(c, -1); int maxa = 0;
for(int i = 1; i < n; ++i) {
ans[i] = (int)(a[n - 1 + i].real() / bit + 0.5) + (int)(b[n - 1 + i].real() / bit + 0.5) + (int)(c[n - 1 + i].real() / bit + 0.5);
maxa = max(maxa, ans[i]);
}
vector<int> pos;
for(int i = 1; i < n; ++i) {
if(ans[i] == maxa) {
pos.push_back(i);
}
}
cout << maxa << endl;
for(int i = 0; i < pos.size(); ++i) {
cout << pos[i] << " ";
}
cout << endl; return 0;
}

SPOJ MAXMATCH - Maximum Self-Matching (FFT)的更多相关文章

  1. Maximum Bipartite Matching

    算法旨在用尽可能简单的思路解决这个问题.理解算法也应该是一个越看越简单的过程,当你看到算法里的一串概念,或者一大坨代码,第一感觉是复杂,此时最好还是从样例入手.通过一个简单的样例,并编程实现,这个过程 ...

  2. SPOJ TSUM Triple Sums(FFT + 容斥)

    题目 Source http://www.spoj.com/problems/TSUM/ Description You're given a sequence s of N distinct int ...

  3. SPOJ - VFMUL - Very Fast Multiplication FFT加速高精度乘法

    SPOJ - VFMUL:https://vjudge.net/problem/SPOJ-VFMUL 这是一道FFT求高精度的模板题. 参考:https://www.cnblogs.com/Rabbi ...

  4. 2018.11.18 spoj Triple Sums(容斥原理+fft)

    传送门 这次fftfftfft乱搞居然没有被卡常? 题目简述:给你nnn个数,每三个数ai,aj,ak(i<j<k)a_i,a_j,a_k(i<j<k)ai​,aj​,ak​( ...

  5. 牛客网暑期ACM多校训练营(第三场)DEncrypted String Matching fft

    题意:给你一个解密后的字符串,给你加密方式,加密过程可能出错,字符可能加减1,然后给你一个字符串,要求匹配个数(其实我也不太懂具体怎么加密解密,反正你把给你的前两个字符串用第三个加密一下,然后搞可以有 ...

  6. SPOJ VFMUL - Very Fast Multiplication (FFT)

    题目链接:VFMUL - Very Fast Multiplication Description Multiply the given numbers. Input n [the number of ...

  7. SPOJ 3693 Maximum Sum(水题,记录区间第一大和第二大数)

    #include <iostream> #include <stdio.h> #include <algorithm> #define lson rt<< ...

  8. 转债---Pregel: A System for Large-Scale Graph Processing(译)

    转载:http://duanple.blog.163.com/blog/static/70971767201281610126277/   作者:Grzegorz Malewicz, Matthew ...

  9. Pregel: A System for Large-Scale Graph Processing(译)

    [说明:Pregel这篇是发表在2010年的SIGMOD上,Pregel这个名称是为了纪念欧拉,在他提出的格尼斯堡七桥问题中,那些桥所在的河就叫Pregel.最初是为了解决PageRank计算问题,由 ...

随机推荐

  1. shell从字符串中提取子串(正则表达式)

    通过试验,可以通过grep.sed两种方式实现. 假设需要提取libgcc-4.8.5-4.h5.x86_64.rpm中的版本号. grep echo "libgcc-4.8.5-4.h5. ...

  2. 关于I2C和SPI总线协议【转】

    关于I2C和SPI总线协议 IICvs SPI 现今,在低端数字通信应用领域,我们随处可见IIC (Inter-Integrated Circuit) 和 SPI (Serial Peripheral ...

  3. 用php写爬虫去爬数据

    参考文档1 参考文档2 这里是我自己写的一个小需求 <?php /** 采集http://www.959.cn/school,即时更新的最新的文章内容:每分钟采集一次.采集结束后实时入库并展示. ...

  4. Dubbo入门到精通学习笔记(十八):使用Redis3.0集群实现Tomcat集群的Session共享

    文章目录 1.单节点访问http://192.168.1.61:8082/pay-web-boss/: 2.增加多一个消费者节点:192.168.1.62,以同样的方式部署pay-web-boss工程 ...

  5. phhstrom 快捷键

    TODO(表示待办事件)注释 快捷键 Alt+6 Alt+6 可以查看添加了//TODO注释的代码片段 一般我们在开发过程中由于时间或者各方面的时间来不及完成的代码,往往会先将逻辑写出来,实现留待以后 ...

  6. 【IO流】java中文件路径(相对路径、绝对路径)相关类及方法

    原文链接:https://blog.csdn.net/Activity_Time/article/details/98034409 1. URL 菜鸟教程:Java URL处理 通常推荐对http等协 ...

  7. HBase 热点问题——rowkey散列和预分区设计

    热点发生在大量的client直接访问集群的一个或极少数个节点(访问可能是读,写或者其他操作).大量访问会使热点region所在的单个机器超出自身承受能力,引起性能下降甚至region不可用,这也会影响 ...

  8. 14-vim-替换命令-01-替换

    命令 英文 功能 工作模式 r replace 替换当前字符 命令模式 R replace 进入替换模式 替换模式 R命令进入替换模式,输入新字符替换当前光标所在位置的字符,替换完成后,按下ESC可以 ...

  9. C# FTP操作代码实现

    C#  FTP 实现方式,废话不多说,直接上代码 public class FtpClient { #region 构造函数 /// <summary> /// 创建FTP工具 /// & ...

  10. 最全的chrome显示www和https方法(全版本)

    78以前的老版本 设置如下参数 chrome://flags/#omnibox-ui-hide-steady-state-url-scheme chrome://flags/#omnibox-ui-h ...