bzoj4462: [Jsoi2013]编程作业
KMP还是有点用处的嘛qwq
对于小写字母,修改其为前一个这个小写字母和它的距离
然后跑KMP就行了
跑得飞快
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <algorithm> #define N 1000006 #define M 100005 using namespace std; int nxt[M],m,pre_mode[M];char mode[M]; int n,pre[N];char s[N]; int last[256]; bool equal(int x,int y,int nowlen){ return x==y||x>nowlen&&y>nowlen; } void work(){ scanf("%s%s",s+1,mode+1); n=strlen(s+1);m=strlen(mode+1); memset(last,0,sizeof(last)); for (int i=1;i<=m;++i) if (mode[i]>'Z'){pre_mode[i]=i-last[mode[i]];last[mode[i]]=i;} else pre_mode[i]=-mode[i]; memset(last,0,sizeof(last)); for (int i=1;i<=n;++i) if (s[i]>'Z'){pre[i]=i-last[s[i]];last[s[i]]=i;} else pre[i]=-s[i]; int j=nxt[0]=nxt[1]=0; for (int i=2;i<=m;++i){ while (j&&!equal(pre_mode[j+1],pre_mode[i],j)) j=nxt[j]; if (equal(pre_mode[j+1],pre_mode[i],j)) ++j; nxt[i]=j; } j=0; int ans=0; for (int i=1;i<=n;++i){ while (j&&!equal(pre_mode[j+1],pre[i],j)) j=nxt[j]; if (equal(pre_mode[j+1],pre[i],j)) ++j; if (j==m){++ans;j=nxt[j];} } printf("%d\n",ans); } int main(){ int T;scanf("%d",&T); while (T--) work(); return 0; }