一直TLE第一个点求助
查看原帖
一直TLE第一个点求助
77584
MessageBoxA楼主2024/4/16 20:29

用的是第一篇题解的PAM+DP的思路,其他点最慢也只跑了3s,第一个点跑了10s+,感觉不大可能是常数问题,是不是遇到边界情况被卡了,但是没有提供数据下载,求调谢谢qwq

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
int n,last,vcnt=1,ans;
int s[MAXN],pam[MAXN][4],fail[MAXN],len[MAXN],f[MAXN],nxt[MAXN];
inline int getfail(int x,int cur){
    while(x!=1 && (cur-len[x]-1<0 || s[cur]!=s[cur-len[x]-1])) x=fail[x];
    return x;
}
inline void add(int ch,int ind){
    int fa=getfail(last,ind);
    if(!pam[fa][ch]){
        vcnt++;
        len[vcnt]=len[fa]+2;
        int fafail=getfail(fail[fa],ind);
        fail[vcnt]=pam[fafail][ch];
        pam[fa][ch]=vcnt;
        if(len[vcnt]<=2) nxt[vcnt]=fail[vcnt];
        else{
            int cur=nxt[fa];
            while(ind-len[cur]-1<0 || s[ind-len[cur]-1]!=s[ind] || (len[cur]+2)*2>len[vcnt]) cur=fail[cur];//len[cur]+2 > len[vcnt]/2
            nxt[vcnt]=pam[cur][ch];
        }
    }
    last=pam[fa][ch];
}
int main(){
    int t;
    string str;
    cin>>t;
    while(t--){
        cin>>str;
        n=str.size();

        memset(pam,0,sizeof(pam));
        memset(fail,0,sizeof(fail));
        fail[0]=1;fail[1]=1;
        len[0]=0;len[1]=-1;
        last=0;
        ans=n;
        vcnt=1;

        for(int i=0;i<n;i++){
            if(str[i]=='A') s[i]=0;
            else if(str[i]=='T') s[i]=1;
            else if(str[i]=='C') s[i]=2;
            else if(str[i]=='G') s[i]=3;
            add(s[i],i);
        }
        for(int i=2;i<=vcnt;i++) f[i]=len[i];
        queue<int>q;
        f[0]=1;q.push(0);
        while(!q.empty()){
            int cur=q.front();q.pop();
            for(int i=0;i<4;i++){
                if(!pam[cur][i]) continue;
                int v=pam[cur][i];
                f[v]=min(f[v],f[cur]+1);
                f[v]=min(f[v],f[nxt[v]]+(len[v]/2-len[nxt[v]])+1);
                ans=min(ans,f[v]+(n-len[v]));
                q.push(v);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
2024/4/16 20:29
加载中...