ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-07-27 15:00:56  阅读:149  来源: 互联网

标签:head ch NOI int 题解 tot 后缀 P7469 str


简要题意:

给定两个字符串 \(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\n",(clock()-st)/CLOCKS_PER_SEC);
    return 0;
}
/*
5
bcabc
bbcca
*/

标签:head,ch,NOI,int,题解,tot,后缀,P7469,str
来源: https://www.cnblogs.com/NuoCarter/p/15065922.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有