P5484 [JLOI2011] 基因补全

P5484 [JLOI2011] 基因补全

拿到这题第一眼:kmp?第二眼:ac自动机?沉思5分钟后:不对……

我们思考这是怎么一个问题:求T串在S串中所有子串的匹配次数

这竟然是道欢乐dp题,记dp[i][j]为S串考虑到i,T串以j结尾的总匹配数,显然有dp[i][t[j]]+=dp[i-1][t[j-1]]。

但是我们发现这题的方案可能有很多,__int128都能爆的那种,所以我们要整高精度

然后这题就做完了

Code:

#include<bits/stdc++.h>
const int N=3005;
using namespace std;
struct ANS{
    char val[N];
    int cnt;
}dp[N];
int f[N];
inline void add(ANS &a,ANS b)
{
    a.cnt=b.cnt>a.cnt ? b.cnt : a.cnt;
    for(int i=1;i<=a.cnt;i++)
    {
        a.val[i]+=b.val[i];
        a.val[i+1]+=a.val[i]/10;
        a.val[i]%=10;
    }
    a.cnt+=a.val[a.cnt+1] ? 1 : 0;
}
void init(ANS &a)
{
    for(int i=0;i<N;i++){a.val[i]=0;}
    a.cnt=1;
}
int n,m;
char s[N],t[N];
int a[N],b[N];
map<char,char> tans;
map<char,int> id;
int pos[5][N],cnt[5];
void work()
{
    cin>>n>>m;
    //A T C G
    //1 2 3 4
    tans['A']='T';tans['T']='A';
    tans['C']='G';tans['G']='C';
    id['A']=1,id['T']=2,id['C']=3,id['G']=4;
    scanf("%s",s+1);for(int i=1;i<=n;i++){s[i]=tans[s[i]];}
    scanf("%s",t+1);
    for(int i=1;i<=n;i++){a[i]=id[s[i]];}
    for(int i=1;i<=m;i++){b[i]=id[t[i]];}
    for(int i=1;i<=m;i++){pos[b[i]][++cnt[b[i]]]=i;init(dp[i]);}
    init(dp[0]);
    dp[0].val[1]=1;
    //f[0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=cnt[a[i]];j;j--)
        {
            int x=pos[a[i]][j];
            add(dp[x],dp[x-1]);
            //f[x]+=f[x-1];
        }
        //cout<<f[m]<<"\n";

    }
    for(int i=dp[m].cnt;i;i--)
    {
        putchar('0'+dp[m].val[i]);
    }
}
int main()
{
    //freopen("1.in","r",stdin);freopen("gen.out","w",stdout);
    work();
    return 0;
}
posted @ 2024-12-06 11:59  liuboom  阅读(9)  评论(0)    收藏  举报