HDU 5763 Another Meaning(FFT)

【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5763

【题目大意】

  给出两个串S和T,可以将S串中出现的T替换为*,问S串有几种表达方式。

【题解】

  我们定义数组f为S串中T出现的最后一个字母所在的位置,那么ans[i]=ans[i-1]+f[i-1]?ans[i-lenT]:0,一遍递推即可,所以关键就在于求出f数组了,f数组可以用kmp求,由于最近练FFT,用FFT求距离卷积匹配为0的位置,就是f数组了。

【代码】

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=524300;
int n,pos[N];
namespace FFT{
    struct comp{
        double r,i;
        comp(double _r=0,double _i=0):r(_r),i(_i){}
        comp operator +(const comp&x){return comp(r+x.r,i+x.i);}
        comp operator -(const comp&x){return comp(r-x.r,i-x.i);}
        comp operator *(const comp&x){return comp(r*x.r-i*x.i,i*x.r+r*x.i);}
        comp conj(){return comp(r,-i);}
    }A[N],B[N];
    const double pi=acos(-1.0);
    void FFT(comp a[],int n,int t){
        for(int i=1;i<n;i++)if(pos[i]>i)swap(a[i],a[pos[i]]);
        for(int d=0;(1<<d)<n;d++){
            int m=1<<d,m2=m<<1;
            double o=pi*2/m2*t;
            comp _w(cos(o),sin(o));
            for(int i=0;i<n;i+=m2){
                comp w(1,0);
                for(int j=0;j<m;j++){
                    comp& A=a[i+j+m],&B=a[i+j],t=w*A;
                    A=B-t;B=B+t;w=w*_w;
                }
            }
        }if(t==-1)for(int i=0;i<n;i++)a[i].r/=n;
    }
}
const int mod=1e9+7;
int T,Cas=1,l1,l2,ans[N],cnt=0,a[N],b[N],f[N];
FFT::comp A[N],B[N],C[N];
char s1[N],s2[N];
int main(){
    scanf("%d",&T);
    while(T--){
        scanf(" %s %s",&s1,&s2);
        memset(f,0,sizeof(f));
        memset(ans,0,sizeof(ans));
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        l1=strlen(s1); l2=strlen(s2);
        for(int i=0;i<l1;i++)a[i]=s1[i]-‘a‘+1;
        for(int i=0;i<l2;i++)b[l2-1-i]=s2[i]-‘a‘+1;
        int N=1; while(N<l1+l2)N<<=1;
        int j=__builtin_ctz(N)-1;
        for(int i=0;i<N;i++)C[i]=FFT::comp(0,0);
        for(int i=0;i<N;i++){pos[i]=pos[i>>1]>>1|((i&1)<<j);}
        for(int i=0;i<N;i++)A[i]=FFT::comp(a[i]*a[i]*a[i],0),B[i]=FFT::comp(b[i],0);
        FFT::FFT(A,N,1);FFT::FFT(B,N,1);
        for(int i=0;i<N;i++)C[i]=C[i]+A[i]*B[i];
        for(int i=0;i<N;i++)A[i]=FFT::comp(a[i],0),B[i]=FFT::comp(b[i]*b[i]*b[i],0);
        FFT::FFT(A,N,1);FFT::FFT(B,N,1);
        for(int i=0;i<N;i++)C[i]=C[i]+A[i]*B[i];
        for(int i=0;i<N;i++)A[i]=FFT::comp(a[i]*a[i],0),B[i]=FFT::comp(b[i]*b[i],0);
        FFT::FFT(A,N,1);FFT::FFT(B,N,1);
        for(int i=0;i<N;i++)C[i]=C[i]-A[i]*B[i]*FFT::comp(2,0);
        FFT::FFT(C,N,-1);
        for(int i=l2-1;i<l1;i++){
            if(C[i].r<0.5)f[i]=1;
        }ans[0]=1;
        for(int i=1;i<=l1;i++){
            ans[i]=ans[i-1];
            if(f[i-1])ans[i]+=ans[i-l2];
            if(ans[i]>mod)ans[i]-=mod;
        }printf("Case #%d: %d\n",Cas++,ans[l1]);
    }return 0;
}

  

时间: 2024-12-16 13:05:06

HDU 5763 Another Meaning(FFT)的相关文章

HDU 5763 Another Meaning(DP+KMP)

http://acm.hdu.edu.cn/showproblem.php?pid=5763 题意: 给出一个字符串和一个模式串,模式串有两种意思,问这句话有几种意思. 思路:因为肯定要去字符串去找模式串,所以首先用KMP计算next数组,然后用动态规划,d[i]表示分析到第i个字符时有多少种意思. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio>

Hdu 1402 (FFT)

题目链接 A * B Problem Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 12490    Accepted Submission(s): 2206 Problem Description Calculate A * B. Input Each line will contain two integers A and

hdu 4970 Killing Monsters(数学题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4970 Problem Description Kingdom Rush is a popular TD game, in which you should build some towers to protect your kingdom from monsters. And now another wave of monsters is coming and you need again to k

HDU 5763 Another Meaning

HDU 5763 Another Meaning 题意:一个字串有可能在模式串出现多次,问有多少种可能出现的情况.关键是有重合的字串是不能同时计入的. 思路:先用kmp求出所有字串的位置.然后,dp. 二维的时候:dp[i][j] i表示前i个子串,j的值1表示一定用这个串,0表示不用.值表示字串出现的情况数. 一维的时候可以直接用dp[i] 表示前i个字串能出现的情况. 然后,状态转移就都是分为三种情况: 1)当前子串和前一个子串不冲突,dp[i] = dp[i-1] * 2. 或者 dp[i

HDU 1045 - Fire Net (最大独立集)

题意:给你一个正方形棋盘.每个棋子可以直线攻击,除非隔着石头.现在要求所有棋子都不互相攻击,问最多可以放多少个棋子. 这个题可以用搜索来做.每个棋子考虑放与不放两种情况,然后再判断是否能互相攻击来剪枝.最后取可以放置的最大值. 这里我转化成求最大独立集来做. 首先将每个空地编号,对于每个空地,与该位置可以攻击到的空地连边.找最多的空地使得不互相攻击,即求该图的最大独立集.与搜索做法基本一致,但是说法略有不同. 1 #include<iostream> 2 #include<cstring

hdu oj1102 Constructing Roads(最小生成树)

Constructing Roads Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13995    Accepted Submission(s): 5324 Problem Description There are N villages, which are numbered from 1 to N, and you should

HDU 1863 畅通工程 (最小生成树)

Problem Description 省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可).经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本.现请你编写程序,计算出全省畅通需要的最低成本. Input 测试输入包含若干测试用例.每个测试用例的第1行给出评估的道路条数 N.村庄数目M ( < 100 ):随后的 N 行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间

hdu 3650 Hot Expo(贪心)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3650 --------------------------------------------------------------------------------------------------------------------------------------------

HDU 3572 Task Schedule(ISAP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3572 题意:m台机器,需要做n个任务.第i个任务,你需要使用机器Pi天,且这个任务要在[Si  ,  Ei]区间内完成才有效.对于一个任务,只能由一个机器来完成,一个机器同一时间只能做一个任务.当然,一个任务可以分成几段不连续的时间来完成.问,能否做完全部任务. 题意很清晰,也就是判断是否是满流. 对于网络流问题,模板大家都有,关键在于如何建图(详见资料) 思路:今天问了龙哥,对建图有了一定的了解,