BZOJ4641 基因改造[KMP]
这道题以前好像模拟的时候做过,当时不会做,于是用hash水过去了。。
正解是KMP,还是用当前字符与上一次相同字符位置的距离表示数组,于是数值相等时就代表相似。第一次出现用INF代替。
然后要匹配有多少个。暴力匹配的话是:匹配到$s_i,t_{j+1}$时,若$s_i=t_{j+1}$或者是$s_i>j$且$t_{j+1}>j$。这表示距离相同或者第一次出现时的匹配。
注意第一次出现的判断:因为从$s$串某一处开始,后面有的字符的距离值不是INF但与之相聚$d$的字符却不在匹配串范围内。
这就要求有上面那个条件。
于是KMP匹配,匹配成功一个字符的条件也就是上面那个。当我失配的时候,也保证是对的说。不太会讲,可以自己yy。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define dbg(x) cerr << #x << " = " << x <<endl 7 using namespace std; 8 typedef long long ll; 9 typedef double db; 10 typedef pair<int,int> pii; 11 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 12 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;} 14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;} 15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;} 16 template<typename T>inline T read(T&x){ 17 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 18 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 19 } 20 const int N=1e6+7,INF=114514810+1919; 21 int pres[N],pret[N],slas[N],tlas[N]; 22 int nxt[N],ans[N],cnt; 23 int T,C,m,n; 24 25 int main(){//freopen("5.in","r",stdin);freopen("5.ans","w",stdout); 26 read(T),read(C);while(T--){ 27 read(n),read(m); 28 memset(slas,0,sizeof slas),memset(tlas,0,sizeof tlas);cnt=0; 29 for(register int i=1,x;i<=n;++i)read(x),pres[i]=slas[x]?i-slas[x]:INF,slas[x]=i; 30 for(register int i=1,x;i<=m;++i)read(x),pret[i]=tlas[x]?i-tlas[x]:INF,tlas[x]=i; 31 nxt[1]=0;int j=0;pret[m+1]=0,pres[n+1]=0; 32 for(register int i=2;i<=m;++i){ 33 while(j&&!(pret[j+1]==pret[i]||pret[i]>j&&pret[j+1]>j))j=nxt[j]; 34 nxt[i]=(pret[j+1]==pret[i]||pret[i]>j&&pret[j+1]>j)?++j:0; 35 } 36 j=0; 37 for(register int i=1;i<=n;++i){//dbg(i),dbg(j); 38 while(j&&!(pres[i]==pret[j+1]||pret[j+1]>j&&pres[i]>j))j=nxt[j]; 39 (pres[i]==pret[j+1]||pret[j+1]>j&&pres[i]>j)&&(++j); 40 if(j==m)ans[++cnt]=i-j+1; 41 } 42 printf("%d\n",cnt); 43 for(register int i=1;i<=cnt;++i)printf("%d ",ans[i]); 44 puts(""); 45 } 46 return 0; 47 }