FFT字符串区间匹配最大值
Posted 爷灬傲奈我何123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FFT字符串区间匹配最大值相关的知识,希望对你有一定的参考价值。
FFT能处理模式串和匹配串的最大匹配问题。
通常是把模式串翻转,然后分字母对答案的贡献,最后取个最大值就可以了。
链接
题意
给你两个串,长度分别为n,m。每个串由三个字符组成’R’,‘P’,‘S’,分别代表着石头剪刀布,第一个串代表是机器出的,第二个串代表是你出的,现在,你已知了机器出的顺序,可以跳过任意个,但是一旦开始就必须进行到比赛结束,所以,问最多赢几盘?
数据范围: 1 < m < n < 1 e 5 1<m<n<1e51<m<n<1e5
代码:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1000010;
const double PI=acos(-1);
struct Complex{
double x;
double y;
Complex operator*(const Complex&tt)const
{
return {x*tt.x-y*tt.y,x*tt.y+y*tt.x};
}
Complex operator-(const Complex&tt)const{
return {x-tt.x,y-tt.y};
}
Complex operator+(const Complex&tt)const
{
return {x+tt.x,y+tt.y};
}
}a[N],b[N];
int tot;
int bit;
int rev[N];
void fft(Complex a[],int inv)
{
for(int i=0;i<tot;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int mid=1;mid<tot;mid*=2)
{
Complex w={cos(PI/mid),inv*sin(PI/mid)};
for(int i=0;i<tot;i+=2*mid)
{
Complex wk={1,0};
for(int j=0;j<mid;j++,wk=wk*w)
{
auto x=a[i+j];
auto y=wk*a[i+j+mid];
a[i+j]=x+y;
a[i+j+mid]=x-y;
}
}
}
if(inv==-1)
for(int i=0;i<tot;i++)
a[i].x/=tot;
}
string s,t;
int ans[N];
int n,m;
void solve(char x,char y)
{
for(int i=0;i<tot;i++)
{
a[i].x=0;
b[i].x=0;
b[i].y=0;
a[i].y=0;
}
for(int i=0;i<s.size();i++)
if(s[i]==y)
a[i].x=1;
for(int i=0;i<t.size();i++)
if(t[i]==x)
b[i].x=1;
fft(a,1),fft(b,1);
for(int i=0;i<tot;i++)
a[i]=a[i]*b[i];
fft(a,-1);
for(int i=m-1;i<tot;i++)
ans[i]+=int(a[i].x+0.5);
}
int main()
{
cin >> n >> m ;
cin>>s;
cin>>t;
reverse(t.begin(),t.end());
while((1<<bit)<n+m) bit++;
tot=(1<<bit);
for(int i=0;i<tot;i++)
rev[i]=((rev[i>>1]>>1) | (i&1)<<(bit-1));
solve('R','S');
solve('S','P');
solve('P','R');
int maxv=0;
for(int i=m-1;i<tot;i++)
maxv=max(maxv,ans[i]);
cout<<maxv<<endl;
return 0;
}
以上是关于FFT字符串区间匹配最大值的主要内容,如果未能解决你的问题,请参考以下文章
2021-12-24:划分字母区间。 字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。 力扣763。某大厂面试