NC20206. [JSOI2013]编程作业
描述
输入描述
第一行包含一个整数 Q表示此数据中一共包含 Q个询问。
接下来 2Q行,每两行为一个询问。
每个询问中的第一行包含一个字符串 S,表示完整代码,
第二行包含一个字符串 T,表示需要检测出现次数的代码片段。
输出描述
一共输出 Q行,每行一个整数,表示对应代码片段的出现次数。
示例1
输入:
3 AiBjCiDECjDiFGC AaBiCaDECiDaFGC cDEcDEbDE aDEbDE ccddef aab
输出:
1 1 2
说明:
【样例说明】C++14(g++5.4) 解法, 执行用时: 31ms, 内存消耗: 13296K, 提交时间: 2020-07-14 22:55:06
#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #define iinf 0x3f3f3f3f #define linf (1ll<<60) #define eps 1e-8 #define maxn 1000010 #define maxe 1000010 #define cl(x) memset(x,0,sizeof(x)) #define rep(i,a,b) for(i=a;i<=b;i++) #define drep(i,a,b) for(i=a;i>=b;i--) #define em(x) emplace(x) #define emb(x) emplace_back(x) #define emf(x) emplace_front(x) #define fi first #define se second #define de(x) cerr<<#x<<" = "<<x<<endl using namespace std; using namespace __gnu_pbds; typedef long long ll; typedef pair<int,int> pii; typedef pair<ll,ll> pll; ll read(ll x=0) { ll c, f(1); for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f; for(;isdigit(c);c=getchar())x=x*10+c-0x30; return f*x; } struct KMP { int n, next[maxn], t[maxn]; bool cmp(int a, int b, int p){return a==b or a>p and b>p;}; void build(int *r, int len) { int i, j=0; n=len; for(i=1;i<=len;i++)t[i]=r[i]; t[len+1]=0; for(i=2;i<=len;i++) { for(;j and !cmp(t[j+1],t[i],j);j=next[j]); next[i] = cmp(t[j+1],t[i],j)?++j:0; } } int move(int pos, int x) { for(;pos and !cmp(t[pos+1],x,pos);pos=next[pos]); return cmp(t[pos+1],x,0) ? pos+1 : 0; } }kmp; ll last[maxn], pre[maxn]; int S[maxn], T[maxn]; char s[maxn], t[maxn]; int main() { ll Q=read(); while(Q--) { ll i, j, n, m; scanf("%s%s",s+1,t+1); n=strlen(s+1); m=strlen(t+1); rep(i,0,300)last[i]=-1; rep(i,1,n) { pre[i]=last[s[i]]; last[s[i]]=i; if(islower(s[i]))S[i] = i-pre[i]; else S[i]=-s[i]; } rep(i,0,300)last[i]=-1; rep(i,1,m) { pre[i]=last[t[i]]; last[t[i]]=i; if(islower(t[i]))T[i] = i-pre[i]; else T[i]=-t[i]; } // de("debug1"); kmp.build(T,m); ll ans=0, p=0; rep(i,1,n) { p = kmp.move(p,S[i]); if(p==m)ans++, p=kmp.next[p]; } printf("%lld\n",ans); } return 0; }
C++(g++ 7.5.0) 解法, 执行用时: 75ms, 内存消耗: 17176K, 提交时间: 2022-11-29 14:11:23
#include<bits/stdc++.h> #define ull unsigned long long #define ll long long #define pb push_back #define ft first #define sd second #define pii pair<int,int> #define pll pair<ll,ll> using namespace std; const int maxn=2e6+10; int nt[maxn],pre[maxn],pos2[maxn],pos1[maxn]; char s1[maxn],s2[maxn]; void getpre(char s[],int pos[],int n) { for(int i=0;i<=128;i++) pre[i]=-1; for(int i=0;i<n;i++){ if(s[i]>='A'&&s[i]<='Z') {pos[i]=s[i]-'A'+1;continue;} if(pre[s[i]-'a']==-1) pos[i]=-1; else pos[i]=i-pre[s[i]-'a']+30; pre[s[i]-'a']=i; } } void getnt(int s[],int n) { int i=0,j=-1; nt[0]=-1; while(i<n){ if(j==-1||(j+30<s[i]?s[j]==-1:s[i]==s[j])) i++,j++,nt[i]=j; else j=nt[j]; } } int kmp(int s[],int p[],int n,int m) { getnt(p,m); int i=0,j=0,ans=0; while(i<n){ if(j==-1||(j+30<s[i]?p[j]==-1:s[i]==p[j])) i++,j++; else j=nt[j]; if(j==m) ans++; } return ans; } int main() { int t; cin>>t; while(t--){ memset(pos1,0,sizeof(pos1)); memset(pos2,0,sizeof(pos2)); cin>>s1>>s2; int n=strlen(s1),m=strlen(s2); getpre(s1,pos1,n); getpre(s2,pos2,m); printf("%d\n",kmp(pos1,pos2,n,m)); } return 0; }
C++(clang++11) 解法, 执行用时: 19ms, 内存消耗: 5368K, 提交时间: 2020-10-30 00:56:59
#include<bits/stdc++.h> using namespace std; const int M=1e6+9; int n,m; int a[M],b[M],f[M],last[209]; char s[M],t[M]; bool cmp(int x,int y,int newletter){ return x==y||(x>=newletter&&y>=newletter); } void work(int ans=0){ scanf("%s%s",s+1,t+1); m=strlen(t+1);a[m+1]=0; n=strlen(s+1);b[n+1]=0; for(int i=1,j=0;i<=m;f[++i]=++j){ if(t[i]>'Z'){a[i]=i-last[t[i]];last[t[i]]=i;} else a[i]=-t[i]; while(j&&!cmp(a[i],a[j],j))j=f[j]; } memset(last,0,sizeof(last)); for(int i=1,j=1;i<=n;++i,++j){ if(s[i]>'Z'){b[i]=i-last[s[i]];last[s[i]]=i;} else b[i]=-s[i]; while(j&&!cmp(b[i],a[j],j))j=f[j]; if(j==m)ans++; } memset(last,0,sizeof(last)); printf("%d\n",ans); } int main(){ int T;scanf("%d",&T); while(T--)work(); return 0; }