作为考试第一题,难度比较小,开始时忘记KMP打法,于是先做第二题了,迅速水完第二题
回来想了想,其实单论数据范围hash明显可解甚至更快
KMP时间复杂度O(n+m)即两个字符串长度
hash该题中复杂度O(n).........
没啥可说的
hash:

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 #include<cmath> 7 #include<stack> 8 #include<map> 9 #include<queue> 10 #define ps push_back 11 #define MAXN 205101 12 #define ll unsigned long long 13 using namespace std; 14 int T; 15 ll hash_A,hash_B,hash_AA,hash_BB; 16 int la,lb; 17 ll base=131ll; 18 ll base1=1ll; 19 char a[MAXN],b[MAXN]; 20 char c; 21 ll bass,bass1; 22 int main() 23 { 24 scanf("%d",&T); 25 while(T--) 26 { 27 scanf("%d%d",&la,&lb); 28 if(lb<=10000) 29 { 30 scanf("%s",a+1); 31 base=131; 32 base1=1; 33 hash_A=0;hash_B=0; 34 for(int i=1;i<=lb;++i) 35 { 36 b[i]=a[i]; 37 } 38 cin>>c; 39 lb++; 40 b[lb]=c; 41 int kx=0; 42 int ans=0; 43 for(int i=lb;i>=1;--i) 44 { 45 kx++; 46 hash_A=(hash_A*base)+(a[kx]-'a'+1); 47 hash_B=(b[i]-'a'+1)*base1+hash_B; 48 base1*=base; 49 //printf("i=%d ",i); 50 //cout<<a[kx]<<b[i]<<endl; 51 //printf("hase_A=%lld B=%lld ",hash_A,hash_B); 52 if(hash_A==hash_B) 53 { 54 ans=kx; 55 } 56 } 57 printf("%d ",ans); 58 base=131; 59 base1=1; 60 hash_A=0;hash_B=0; 61 } 62 else 63 { 64 scanf("%s",a+1); 65 base=131;bass=1331; 66 base1=1;bass1=1; 67 hash_A=hash_B=hash_AA=hash_BB=0; 68 for(int i=1;i<=lb;++i) 69 { 70 b[i]=a[i]; 71 } 72 cin>>c; 73 lb++; 74 b[lb]=c; 75 int kx=0; 76 int ans=0; 77 for(int i=lb;i>=1;--i) 78 { 79 kx++; 80 hash_A=(hash_A*base)+(a[kx]-'a'+1); 81 hash_B=(b[i]-'a'+1)*base1+hash_B; 82 83 hash_AA=(hash_AA*bass)+(a[kx]-'a'+1); 84 hash_BB=(b[i]-'a'+1)*bass1+hash_BB; 85 86 base1*=base; 87 bass1*=bass; 88 //printf("i=%d ",i); 89 //cout<<a[kx]<<b[i]<<endl; 90 //printf("hase_A=%lld B=%lld ",hash_AA,hash_BB); 91 if(hash_A==hash_B&&hash_AA==hash_BB) 92 { 93 ans=kx; 94 } 95 } 96 printf("%d ",ans); 97 base=131;bass=1331; 98 base1=1;bass1=1; 99 hash_A=hash_B=hash_AA=hash_BB=0; 100 } 101 } 102 } 103 /* 104 2 105 5 3 106 adabc 107 d 108 */
(为了防数据卡我,我还打了双hash,好像没啥必要......)
KMP:
考后复习了一下
首先next数组 next[i]表示该字符串以i结尾的最长后缀==前缀的长度
定义指针j=0从i=2开始移动(由定义可知next[1]=0)
然后while(j!=0&&a[j+1]!=a[i])j=next[j];
应用了next数组的性质,若是当前的字符和指针的下一个字符不匹配就向前移动
(由next数组定义可知,这样移动正确)
然后求解f数组相似不再细说
(其实暴力的字符串用hash都能过.......)

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 #include<cmath> 7 #include<stack> 8 #include<map> 9 #include<queue> 10 #define ps push_back 11 #define MAXN 205101 12 #define ll unsigned long long 13 using namespace std; 14 int T; 15 int la,lb; 16 char a[MAXN],b[MAXN]; 17 int nxt[MAXN],f[MAXN]; 18 char c; 19 int main() 20 { 21 scanf("%d",&T); 22 while(T--) 23 { 24 memset(nxt,0,sizeof(nxt)); 25 memset(f,0,sizeof(f)); 26 scanf("%d%d",&la,&lb); 27 scanf("%s",a+1); 28 for(int i=1;i<=lb;++i) 29 { 30 b[i]=a[i]; 31 } 32 cin>>c; 33 lb++; 34 b[lb]=c; 35 nxt[1]=0; 36 for(int i=2,j=0;i<=la;++i) 37 { 38 while(j>0&&a[i]!=a[j+1])j=nxt[j]; 39 if(a[i]==a[j+1])j++; 40 41 nxt[i]=j; 42 } 43 for(int i=1,j=0;i<=lb;++i) 44 { 45 while(j>0&&(j==la||b[i]!=a[j+1])) 46 { 47 //printf("j=%d ",j); 48 j=nxt[j];} 49 if(b[i]==a[j+1])j++; 50 51 f[i]=j;//printf("i=%d %d ",i,f[i]); 52 } 53 printf("%d ",f[lb]); 54 } 55 } 56 /* 57 2 58 5 3 59 adabc 60 d 61 */