Description
匹配字符串A,B,匹配条件是在A长度为=B的子串中,排名顺序相同.
Sol
KMP+树状数组.
KMP匹配的时候计算排名就可以了啊...这个东西可以用树状数组维护.
这题是个双倍经验啊...
其实不用树状数组也可以,因为字符集很小,开个什么数组就可以搞,我就根据辣个题改了改而已...
Code
/************************************************************** Problem: 1462 User: BeiYu Language: C++ Result: Accepted Time:1340 ms Memory:3676 kb ****************************************************************/ #include<cstdio> #include<cstring> #include<iostream> using namespace std; #define N 100005 #define M 10005 int a[N],b[N],rk1[N],rk2[N],f[N],ans[N];int c[M]; int n,m,s,t; inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x; } inline int lowbit(int x){return x&(-x);} inline void add(int x,int v){while(x<M) c[x]+=v,x+=lowbit(x);} inline int sum(int x,int res=0){while(x) res+=c[x],x-=lowbit(x);return res;} int solve(){ m=in(),n=in(); memset(c,0,sizeof(c)); for(int i=0;i<m;i++) b[i]=in(),add(b[i],1),rk1[i]=sum(b[i]-1),rk2[i]=sum(b[i]); for(int i=0;i<n;i++) a[i]=in(); memset(c,0,sizeof(c)); for(int i=1,j;i<m;i++){ j=f[i];add(b[i],1); while(j&&(sum(b[j]-1)!=rk1[i]||sum(b[j])!=rk2[i])){ for(int p=i-j;p<i-f[j];p++) add(b[p],-1); j=f[j]; } f[i+1]=(rk1[j]==sum(b[i]-1)&&rk2[j]==sum(b[i]))?j+1:0; } memset(c,0,sizeof(c)); for(int i=0,j=0;i<n;i++){ add(a[i],1); while(j&&(sum(a[i]-1)!=rk1[j]||sum(a[i])!=rk2[j])){ for(int p=i-j;p<i-f[j];p++) add(a[p],-1); j=f[j]; } if(sum(a[i]-1)==rk1[j]&&sum(a[i])==rk2[j]) j++; if(j==m){ return i-j+1; for(int p=i-j+1;p<=i;p++) add(a[p],-1); j=0; } }return -1; } int main(){ for(int T=in();T--;){ int tmp=solve(); if(~tmp) printf("%d ",tmp); else puts("no solution!"); } return 0; }