题目链接:点这里!!!
题意:
给定两个数组a(文本串),b(模式串)。问文本串能匹配出多少个模式串(不允许重叠)。"匹配"的意思各自离散化之后的串是一样的。
例如:(20,2,2,5,1,3,21) 与 (10 10 15,1) 。(2,2,5,7)与(10,10,15,1)是匹配的。
数据范围len<=1e5, 1<=k<=5,1<=a[i]<=k
题解:
1、首先看到这种题目涉及到模式串的匹配问题,很容易往kmp方面想。
2、但是这里的匹配略有不同,这里的匹配指的相对大小关系的匹配,所以我们在kmp上判相等的时候略有不同。
3、如何判断相对大小关系是不是相等。
我们可以统计当前:
比a[i]小的有多少,等于a[i]的有多少,比a[i]大的有多少;
比b[j]小的有多少,等于b[j]的有多少,比b[j]大的有多少;
如果两两都相等的话,说明相对大小关系是一样的。
4、至于如何去统计,可以利用前缀和即可,看代码。
5、代码:
#include<cstdio> #include<cstring> #include<iostream> #include<sstream> #include<algorithm> #include<vector> #include<bitset> #include<set> #include<queue> #include<stack> #include<map> #include<cstdlib> #include<cmath> #define PI 2*asin(1.0) #define LL long long #define pb push_back #define pa pair<int,int> #define clr(a,b) memset(a,b,sizeof(a)) #define lson lr<<1,l,mid #define rson lr<<1|1,mid+1,r #define bug(x) printf("%d++++++++++++++++++++%d\n",x,x) #define key_value ch[ch[root][1]][0]C:\Program Files\Git\bin const int MOD = 1000000007; const int N = 1e5+15; const int maxn = 1e4+1000; const int letter = 130; const int INF = 1e17; const double pi=acos(-1.0); const double eps=1e-8; using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,m,k; int a[N],b[N],f[N]; int ga[N][30],gb[N][30]; /// 前缀和 bool judge_1(int x,int y){ ///gb if(gb[x][b[x]]!=gb[y][b[y]]-gb[y-x][b[y]]) return 0; ///= int sum1=0,sum2=0; for(int i=1;i<b[x];i++) sum1+=gb[x-1][i]; for(int i=1;i<b[y];i++) sum2+=gb[y-1][i]; for(int i=1;i<b[y];i++) sum2-=gb[y-x][i]; return sum1==sum2; } void get_fail(int *p,int *f,int m){ f[1]=0; int j=0; for(int i=2;i<=m;i++){ while(j&&!judge_1(j+1,i)) j=f[j]; if(judge_1(j+1,i)) j++; f[i]=j; } } bool judge_2(int x,int y){ /// x a, y b if(ga[x][a[x]]-ga[x-y][a[x]]!=gb[y][b[y]]) return 0; int sum1=0,sum2=0; for(int i=1;i<a[x];i++) sum1+=ga[x-1][i]; for(int i=1;i<a[x];i++) sum1-=ga[x-y][i]; for(int i=1;i<b[y];i++) sum2+=gb[y-1][i]; return sum1==sum2; } int solve(){ int j=0; int ans=0; for(int i=1;i<=n;i++){ while(j&&!judge_2(i,j+1)) j=f[j]; if(judge_2(i,j+1))j++; if(j==m){ ans++; j=0; } } printf("%d\n",ans); } int main(){ while(scanf("%d%d%d",&n,&m,&k)!=EOF){ clr(ga,0),clr(gb,0); for(int i=1;i<=n;i++) { scanf("%d",a+i); for(int j=1;j<=k;j++) ga[i][j]=ga[i-1][j]; ga[i][a[i]]++; } for(int i=1;i<=m;i++) { scanf("%d",b+i); for(int j=1;j<=k;j++) gb[i][j]=gb[i-1][j]; gb[i][b[i]]++; } get_fail(b,f,m); solve(); } return 0; } /* 10 5 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 */