标签:open 后缀 start sof i++ pre ges pos com
题意:找一个出现了m次的最长子串,以及这时的最右的位置。
hash的话代码还是比较好写的,,但是时间比SA多很多。。
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 using namespace std; 5 const int N = 40000 + 100; 6 typedef long long ll; 7 const int X = 257; 8 const int mod = (int)1e9 + 7; 9 10 char s[N]; 11 int m,len,pw[N]; 12 int H[N],pos; 13 14 struct node 15 { 16 int id,hash; 17 bool operator < (const node & temp) const 18 { 19 return hash == temp.hash ? id < temp.id : hash < temp.hash; 20 } 21 }p[N]; 22 23 bool solve(int L) 24 { 25 int cnt = 0; 26 pos = -1; 27 for(int i=1;i+L-1<=len;i++) 28 { 29 int id = i; 30 int hash = ((ll)H[i] - (ll)H[i+L]*pw[L]) % mod; 31 if(hash < 0) hash += mod; // 注意这里! 32 p[i] = (node){id, hash}; 33 } 34 sort(p+1, p+1+ len - L + 1); 35 36 for(int i=1;i<=len-L+1;i++) 37 { 38 if(i == 1 || p[i].hash != p[i-1].hash) cnt = 0; 39 if(++cnt >= m) pos = max(pos, p[i].id); 40 } 41 return pos != -1; 42 } 43 44 int main() 45 { 46 pw[0] = 1; 47 for(int i=1;i<N;i++) pw[i] = 1LL*pw[i-1] * X % mod; 48 while(scanf("%d",&m) == 1 && m) 49 { 50 scanf("%s",s+1); 51 len = strlen(s+1); 52 for(int i=len;i>=1;i--) H[i] = (1LL*H[i+1] * X + s[i] - ‘a‘) % mod; 53 int l = 1, r = len, ans = -1; 54 while(l <= r) 55 { 56 int mid = l + r >> 1; 57 if(solve(mid)) ans = mid, l = mid + 1; 58 else r = mid - 1; 59 } 60 solve(ans); 61 if(ans != -1) printf("%d %d\n",ans, pos-1); 62 else puts("none"); 63 } 64 return 0; 65 }
SA的话,写法需要细细体会一下了。。时间减少了很多。
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 using namespace std; 5 const int N = 40000 + 100; 6 typedef long long ll; 7 const int X = 257; 8 const int mod = (int)1e9 + 7; 9 10 char s[N]; 11 int m,len,pw[N]; 12 int H[N],pos; 13 14 struct node 15 { 16 int id,hash; 17 bool operator < (const node & temp) const 18 { 19 return hash == temp.hash ? id < temp.id : hash < temp.hash; 20 } 21 }p[N]; 22 23 bool solve(int L) 24 { 25 int cnt = 0; 26 pos = -1; 27 for(int i=1;i+L-1<=len;i++) 28 { 29 int id = i; 30 int hash = ((ll)H[i] - (ll)H[i+L]*pw[L]) % mod; 31 if(hash < 0) hash += mod; // 注意这里! 32 p[i] = (node){id, hash}; 33 } 34 sort(p+1, p+1+ len - L + 1); 35 36 for(int i=1;i<=len-L+1;i++) 37 { 38 if(i == 1 || p[i].hash != p[i-1].hash) cnt = 0; 39 if(++cnt >= m) pos = max(pos, p[i].id); 40 } 41 return pos != -1; 42 } 43 44 int main() 45 { 46 pw[0] = 1; 47 for(int i=1;i<N;i++) pw[i] = 1LL*pw[i-1] * X % mod; 48 while(scanf("%d",&m) == 1 && m) 49 { 50 scanf("%s",s+1); 51 len = strlen(s+1); 52 for(int i=len;i>=1;i--) H[i] = (1LL*H[i+1] * X + s[i] - ‘a‘) % mod; 53 int l = 1, r = len, ans = -1; 54 while(l <= r) 55 { 56 int mid = l + r >> 1; 57 if(solve(mid)) ans = mid, l = mid + 1; 58 else r = mid - 1; 59 } 60 solve(ans); 61 if(ans != -1) printf("%d %d\n",ans, pos-1); 62 else puts("none"); 63 } 64 return 0; 65 }
顺便想说一下的是,这里不知为何下标从1开始无限WA,以后用SA还是下标从0开始好了。。毕竟不懂SA的具体原理。
UVALive - 4513 Stammering Aliens ——(hash+二分 || 后缀数组加二分)
标签:open 后缀 start sof i++ pre ges pos com
原文地址:http://www.cnblogs.com/zzyDS/p/6189539.html