http://acm.ustc.edu.cn/ustcoj/source.php?id=82828
数据是水过去了,但是bug还在(找不出啊);
我把mod改为19998过了,运气啊,可是改成其他东西就过不了,还有uvalive上一直T,哎~,伤不起啊。
最重要的思想:
假如把a[0,m],b[0,m],看成两个多项式,a看作 1,b看作0,那么先把b[0,m]转置,那么有多少个a相同的位是不是等价于多项式系数为m前的系数呢!同理把a看作0,b看作1。
然后就可以在nlogn的时间内得到系数。
最后hash一下字符串就能得到结果。
hash的方法:离散化,map,邻接表
#include <stdio.h>
#include <deque>
#include <set>
#include <string>
#include <map>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
typedef long long LL;
const double Pi = acos(-1.0);
const int maxn = 200005;
map<string,int> mymap;
char a[maxn],b[maxn],c[maxn];
struct complex{
double r,i;
complex(double _r=0, double _i=0){
r = _r;
i = _i;
}
complex operator +(const complex &b){
return complex(r+b.r,i+b.i);
}
complex operator -(const complex &b){
return complex(r-b.r,i-b.i);
}
complex operator *(const complex &b){
return complex(r*b.r-i*b.i,r*b.i+i*b.r);
}
}x[maxn*2],y[maxn*2];
void brc(complex y[],int len){
int i,j,k;
for(i=1,j=len/2;i<len-1;i++){
if(i < j)swap(y[i],y[j]);
k = len / 2;
while(j >= k){
j -= k;
k /= 2;
}
if(j < k)j += k;
}
}
void FFT(complex y[],int len,int on){
brc(y,len);
for(int h=2;h<=len;h<<=1){
complex wn(cos(-on*2*Pi/h),sin(-on*2*Pi/h));
for(int j=0;j<len;j+=h){
complex w(1.0);
for(int k=j;k<j+h/2;k++){
complex u = y[k];
complex t = w * y[k+h/2];
y[k] = u + t;
y[k+h/2] = u - t;
w = w * wn;
}
}
}
if(on == -1){
for(int i=0;i<len;i++){
y[i].r /= len;
}
}
}
int len;
int strlena;
int strlenb;
void mul(int c[],char cmp){
//printf("l:%d\n",strlena);
len = 1;
while(len < strlena)len *= 2;
len *= 2;
for(int i=0;i<strlena;i++){
if(a[i] == cmp){
x[i] = complex(1,0);
}
else {
x[i] = complex(0,0);
}
}
for(int i=strlena;i<len;i++){
x[i] = complex();
}
for(int i=0;i<strlenb;i++){
if(b[i] == cmp){
y[i] = complex(1,0);
}
else {
y[i] = complex(0,0);
}
}
for(int i=strlenb;i<len;i++){
y[i] = complex();
}
FFT(x,len,1);
FFT(y,len,1);
for(int i=0;i<len;i++)x[i] = x[i]*y[i];
FFT(x,len,-1);
for(int i=0;i<strlena+strlenb;i++){
c[i] = x[i].r + 0.5;
}
}
int d1[maxn];
int d2[maxn];
void printarray(int a[],int n){
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
printf("\n");
}
const int maxm = 1e5 + 7;
const int mod = 19998;
struct node{
int v;
int next;
}e[maxm+10];
int head[mod];
int f[maxn];
int tot;
void init(){
memset(head,-1,sizeof(head));
tot = 0;
}
void add(int u,int v){
e[tot].v = v;
e[tot].next = head[u];
head[u] = tot++;
}
int pow2(int n){
int ans = 1;
int a = 2;
while(n){
if(n&1)ans=(ans*a)%mod;
a = a * a % mod;
n >>= 1;
}
return ans;
}
bool check1(int si,int sj){
for(int i=0;i<strlenb;i++){
if(a[si+i] == a[sj+i]){
continue;
}
return false;
}
return true;
}
bool check(int u,int v){
for(int iter=head[u];iter!=-1;iter=e[iter].next){
if(check1(v,e[iter].v)==true){
return true;
}
}
//add(u,v);
return false;
}
int main(){
//string a,c,b;
int k;
int cas = 1;
while(scanf("%d%s%s",&k,a,c), k != -1){
strlena = strlen(a);
strlenb = strlen(c);
//printf("%d\n",k);
//puts(a);
//puts(c);
for(int i=0;i<strlenb;i++){
b[i] = c[strlenb-i-1];
}
b[strlenb] = '\0';
if(strlena < strlenb){
printf("Case %d: %d\n",cas++,0);
continue;
}
mul(d1,'a');
mul(d2,'b');
//printarray(d1,len);
//printarray(d2,len);
//mymap.clear();
/*
for(int i=b.length()-1;i<len;i++){
}
*/
int t = 0;
init();
for(int i=0;i<strlenb;i++){
t = (t * 2 + (a[i] - 'a'));
if(t >= mod)t -= mod;
}
f[0] = t;
add(f[0],0);
int ans = 0;
k = strlenb - k;
if(d1[strlenb-1] + d2[strlenb-1] >= k){
ans ++;
}
int p = pow2(strlenb-1);
for(int i=strlenb,j=1;i<strlena;i++,j++){
f[j] = (((f[j-1] - p*(a[j-1]-'a')%mod + mod)%mod)*2 + a[i]-'a');
if(f[j]>=mod)f[j]-=mod;
//add(f[j+1],j+1);
if(check(f[j],j) == false){
if(d1[i] + d2[i] >= k){
ans ++;
}
add(f[j],j);
}
}
printf("Case %d: %d\n",cas++,ans);
}
return 0;
}