Gym - 101667H Rock Paper Scissors (FFT/NTT求相似度最大的子串)

题目链接

题目大意:给你两个字符串s1,s2,让你从s1中找到与s2相似度最大(对应位相同的字符数最多)的子串。

解法:将s2翻转,对每一种待匹配的字符,将两串中所有该字符的位置都标记为1,然后求卷积,卷积结果中系数最大的那一项即为最大匹配数。将所有待匹配字符对应位的匹配数相加,取最大值即可。

注意这道题有坑,s2的开头不能再s1之前,而结尾有可能在s1之后。

复杂度O((n+m)log(n+m)*k),k为字符种数。

FFT:

#include

using namespace std;
typedef complex cpl;
const double pi=acos(-1);
const int N=1e5+10;
cpl a[N<<2],b[N<<2],c[N<<2];
char s1[N],s2[N];
int n,m,np;

void trans(cpl* a,int n) {
    for(int i=1,j=n>>1,k; i>1;
        while(j>=k)j-=k,k>>=1;
        j+=k;
    }
}

void FFT(cpl* a,int n,int f) {
    trans(a,n);
    for(int k=1; k

NTT:

#include

using namespace std;
typedef long long ll;
const int N=1e5+10;
const ll mod=(119<<23)+1;
const ll G=3;
ll a[N<<2],b[N<<2],c[N<<2];
char s1[N],s2[N];
int n,m,np;

ll Pow(ll x,ll p,ll mod) {
    ll ret=1;
    while(p) {
        if(p&1)ret=ret*x%mod;
        x=x*x%mod;
        p>>=1;
    }
    return ret;
}

void trans(ll* a,int n) {
    for(int i=1,j=n>>1,k; i>1;
        while(j>=k)j-=k,k>>=1;
        j+=k;
    }
}

void NTT(ll* a,int n,int f) {
    trans(a,n);
    for(int k=1; k

 

你可能感兴趣的:(FFT,字符串,NTT)