生活随笔
收集整理的這篇文章主要介紹了
UVA4671 K-neighbor substrings FFT+字符串hash
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題解:
將字符串A、B中的a和b分別以1和-1表示,對字符串B進行反轉(zhuǎn)。
將A和B看成多項式,求卷積,這樣的話從結(jié)果區(qū)間的[lenB?1,lenA)[lenB?1,lenA)中的每一個點的值valval,(lenB?val)/2(lenB?val)/2代表當(dāng)前位置的字串與B串的距離,然后對字串進行字符串hash,去重就是答案。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <set>
using namespace std;
double pi =
acos(-
1.0);
struct complex{
double re,im;
complex(
double r =
0.0,
double i =
0.0):re(r),im(i){};
complex operator+(
complex com){
return complex(re+com.re,im+com.im);}
complex operator-(
complex com){
return complex(re-com.re,im-com.im);}
complex operator*(
complex com){
return complex(re*com.re-im*com.im,re*com.im+im*com.re);}
};
complex wn,wntmp;
void rader(
complex arr[],
int n){
int num = n-
1;
for(
int i =
0;i < n;++i){
int tn = n>>
1;
while(num && num >= tn) num ^= tn,tn >>=
1;num |= tn;
if(num > i) swap(arr[i],arr[num]);}
}
void FFT(
complex cs[],
int n,
int f){rader(cs,n);
for(
int s =
1;s < n;s <<=
1){wn =
complex(
cos(f*
2*pi/(s*
2)),
sin(f*
2*pi/(s*
2)));
for(
int offset =
0;offset < n;offset += s<<
1){wntmp =
complex(
1.0,
0.0);
for(
int i =
0;i < s;++i){
complex u = cs[offset+i],v = cs[offset+i+s]*wntmp;cs[offset+i] = u + v;cs[offset+i+s] = u - v;wntmp = wntmp * wn;}}}
if(f == -
1)
for(
int i =
0;i < n;++i)cs[i].re /= n;
}
int K;
const int maxn =
600007;
char A[maxn],B[maxn];
complex csA[maxn],csB[maxn];
unsigned long long fac =
9973;
unsigned long long pow(
int x){
unsigned long long ans =
1,base = fac;
while(x){
if(x &
1)ans *= base;base *= base;x >>=
1;}
return ans;
}
int main(){
int cas =
0;
while(
cin>>K && K != -
1){
memset(csA,
0,
sizeof(csA)),
memset(csB,
0,
sizeof(csB));
cin>>A>>B;
int lenA =
strlen(A),lenB =
strlen(B);
for(
int i =
0;i < lenB/
2;++i) swap(B[i],B[lenB-i-
1]);
int len =
1;
while(len < lenA || len < lenB) len <<=
1;len <<=
1;
for(
int i =
0;i < lenA;++i) csA[i].re = A[i] ==
'a'?
1:-
1;FFT(csA,len,
1);
for(
int i =
0;i < lenB;++i) csB[i].re = B[i] ==
'a'?
1:-
1;FFT(csB,len,
1);
for(
int i =
0;i < len;++i) csA[i] = csA[i]*csB[i];FFT(csA,len,-
1);
set<unsigned long long> st;
unsigned long long hash =
0,base =
pow(lenB-
1);
for(
int i =
0;i < lenB;++i) hash = hash*fac + (A[i] ==
'a');
long long ans =
0;
for(
int i = lenB-
1;i < lenA;++i){
int dis= (lenB -
int(csA[i].re+
100000.5) +
100000)/
2;
if(dis <= K) st.insert(hash),ans++;hash = (hash - base * (A[i-lenB+
1] ==
'a'))*fac+(A[i+
1] ==
'a');}
printf(
"Case %d: %d\n",++cas,st.size());}
return 0;
}
總結(jié)
以上是生活随笔為你收集整理的UVA4671 K-neighbor substrings FFT+字符串hash的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。