• P7469 [NOI Online 2021 提高组] 积木小赛 题解


    简要题意:

    给定两个字符串 (A,B)

    求出 (B) 的本质不同子串中是 (A) 的子序列的个数

    首先考虑将 子串 转化为后缀的前缀,我们可以枚举整个后缀来获取整个 (B)子串

    枚举后缀是 (O(n)) 的,再用整个后缀去与 (A) 匹配。

    不妨设这个后缀为 (S_{1-i})

    因为 (S_{1-i})(A) 的子序列,那么 (S_{1-(i-1)}) 也一定是 (A) 的子序列。

    于是可以 (O(n)) 模拟得到这个后缀在 (A) 中的最长匹配长度。

    而整个后缀的前缀中,只要 (leq) 这个长度,一定都是 (A) 的子序列。

    总体复杂度 (O(n^2)),但是答案要求的是本质不同的子串。

    所以用一个双哈希判重即可。(考场上写了3个哈希。。)

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const ll MOD=19260919,base=173,MOD2=23532139,base2=239,MOD3=33532139,base3=337;
    const int N=3005;
    
    template <typename T>
    inline void read(T &x){
        x=0;char ch=getchar();bool f=false;
        while(!isdigit(ch)) f|=ch=='-',ch=getchar();
        while(isdigit(ch))  x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;
    }
    template <typename T>
    inline void print(T x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) print(x/10);
        putchar(x%10^48);
    }
    int n,pi[N],ans;
    string a,b,tep,ptr,res;
    pair<ll,ll> str[N*N];
    int head[MOD+2],Next[N*N],tot;
    inline void Add(int u,pair<ll,ll> ins){Next[++tot]=head[u],str[tot]=ins,head[u]=tot;}
    inline bool Find(int u,pair<ll,ll> goal){
        for(register int i=head[u];i;i=Next[i]){
            if(str[i].first==goal.first&&str[i].second==goal.second)   return true;
        }
        return false;
    }
    ll has1,has2,has3;
    int main(){
        // freopen("block.in","r",stdin);
        // freopen("block.out","w",stdout);
        read(n);
        cin>>a>>b;
        for(register int st=0;st<n;++st){
            ptr=b.substr(st,n-st);
            int loc=0;
            for(register int i=0;i<n;++i){if(a[i]==ptr[loc])  loc++;}
            res="";has1=0,has2=0,has3=0;
            for(register int i=0;i<loc;++i){
                res+=ptr[i];
                has1=(has1*base+ptr[i]-'0')%MOD;
                has2=(has2*base2+ptr[i]-'0')%MOD2;
                has3=(has3*base3+ptr[i]-'0')%MOD3;
                if(!Find(has1,make_pair(has2,has3))){
                    Add(has1,make_pair(has2,has3));
                    ans++;
                }
                // cout<<res<<endl;
            }
        }
        print(ans);
        // puts("");
        // printf("%.6lf
    ",(clock()-st)/CLOCKS_PER_SEC);
        return 0;
    }
    /*
    5
    bcabc
    bbcca
    */
    
    
  • 相关阅读:
    【代码笔记】iOS-NSLog的使用
    【代码笔记】iOS-NSJSONSerializationDemo
    【代码笔记】iOS-My97DatePicker日历
    【代码笔记】iOS-mp3的播放
    【代码笔记】iOS-MBProgressHUDDemo
    【代码笔记】iOS-MBProgressHUD
    【代码笔记】iOS-导航条的标题(label)
    【代码笔记】iOS-Label随字自动变大
    OC语言构造方法
    iOS开发UI篇—在ImageView中添加按钮以及Tag的参数说明
  • 原文地址:https://www.cnblogs.com/NuoCarter/p/15065922.html
Copyright © 2020-2023  润新知