• 【HDOJ】4080 Stammering Aliens


    1. 题目描述
    给定一个长为$n in [1, 4000]$的字符串,求其中长度最长的子串,并且该子串在原串中出现至少$m$次,并求最右起始位置。

    2. 基本思路
    两种方法:二分+后缀数组,或者二分+哈希。
    (1) 二分+后缀数组
    对子串长度进行二分,若不同后缀的公共前缀超过这个值,则对计数值累加。若计数值超过m,则证明这个公共前缀是有效的,计数过程中同时维护pos(最右边界),从而更新rpos。

    (2)二分+哈希
    仍然是对长度进行二分,然后枚举其实位置计算该长度的子串的哈希值,排序后,计算,超过m表示是有效的子串,从而更新最右位置。哈希采用LCP哈希。

    3. 代码
    (1)后缀数组

      1 /* 4080 */
      2 #include <iostream>
      3 #include <sstream>
      4 #include <string>
      5 #include <map>
      6 #include <queue>
      7 #include <set>
      8 #include <stack>
      9 #include <vector>
     10 #include <deque>
     11 #include <algorithm>
     12 #include <cstdio>
     13 #include <cmath>
     14 #include <ctime>
     15 #include <cstring>
     16 #include <climits>
     17 #include <cctype>
     18 #include <cassert>
     19 #include <functional>
     20 #include <iterator>
     21 #include <iomanip>
     22 using namespace std;
     23 //#pragma comment(linker,"/STACK:102400000,1024000")
     24 
     25 #define sti                set<int>
     26 #define stpii            set<pair<int, int> >
     27 #define mpii            map<int,int>
     28 #define vi                vector<int>
     29 #define pii                pair<int,int>
     30 #define vpii            vector<pair<int,int> >
     31 #define rep(i, a, n)     for (int i=a;i<n;++i)
     32 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
     33 #define clr                clear
     34 #define pb                 push_back
     35 #define mp                 make_pair
     36 #define fir                first
     37 #define sec                second
     38 #define all(x)             (x).begin(),(x).end()
     39 #define SZ(x)             ((int)(x).size())
     40 #define lson            l, mid, rt<<1
     41 #define rson            mid+1, r, rt<<1|1
     42 
     43 const int maxn = 40005;
     44 char s[maxn];
     45 int a[maxn];
     46 int height[maxn], sa[maxn], rrank[maxn];
     47 int wa[maxn], wb[maxn], wc[maxn], wv[maxn];
     48 int rpos, m;
     49 
     50 bool cmp(int *r, int a, int b, int l) {
     51     return r[a]==r[b] && r[a+l]==r[b+l];
     52 }
     53 
     54 void da(int *r, int *sa, int n, int m) {
     55     int i, j, *x=wa, *y=wb, *t, p;
     56 
     57     for (i=0; i<m; ++i) wc[i] = 0;
     58     for (i=0; i<n; ++i) wc[x[i]=r[i]]++;
     59     for (i=1; i<m; ++i) wc[i] += wc[i-1];
     60     for (i=n-1; i>=0; --i) sa[--wc[x[i]]] = i;
     61     for (j=1,p=1; p<n; j*=2, m=p) {
     62         for (p=0, i=n-j; i<n; ++i) y[p++] = i;
     63         for (i=0; i<n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
     64         for (i=0; i<n; ++i) wv[i] = x[y[i]];
     65         for (i=0; i<m; ++i) wc[i] = 0;
     66         for (i=0; i<n; ++i) wc[wv[i]]++;
     67         for (i=1; i<m; ++i) wc[i] += wc[i-1];
     68         for (i=n-1; i>=0; --i) sa[--wc[wv[i]]] = y[i];
     69         for (t=x,x=y,y=t,x[sa[0]]=0,p=1,i=1; i<n; ++i)
     70             x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++;
     71     }
     72 }
     73 
     74 void calheight(int *r, int *sa, int n) {
     75     int i, j, k = 0;
     76 
     77     for (i=1; i<=n; ++i) rrank[sa[i]] = i;
     78     for (i=0; i<n; height[rrank[i++]]=k)
     79     for (k?k--:0, j=sa[rrank[i]-1]; r[j+k]==r[i+k]; ++k) ;
     80 }
     81 
     82 void printSa(int n) {
     83     for (int i=1; i<=n; ++i)
     84         printf("%d ", sa[i]);
     85     putchar('
    ');
     86 }
     87 
     88 void printHeight(int n) {
     89     for (int i=1; i<=n; ++i)
     90         printf("%d ", height[i]);
     91     putchar('
    ');
     92 }
     93 
     94 bool judge(int bound, int n) {
     95     int cnt = 1, pos = -1;
     96 
     97     rpos = -1;
     98     rep(i, 1, n+1) {
     99         if (height[i] >= bound) {
    100             pos = max(pos, sa[i]);
    101             ++cnt;
    102         } else {
    103             if (cnt >= m)
    104                 rpos = max(pos, rpos);
    105             pos = sa[i];
    106             cnt = 1;
    107         }
    108     }
    109     if (cnt >= m)
    110         rpos = max(pos, rpos);
    111 
    112     return rpos!=-1;
    113 }
    114 
    115 void solve() {
    116     int n;
    117 
    118     for (int i=0; ; ++i) {
    119         if (s[i] == '') {
    120             n = i;
    121             break;
    122         }
    123         a[i] = s[i] - 'a' + 1;
    124     }
    125     a[n] = 0;
    126     if (m == 1) {
    127         printf("%d 0
    ", n);
    128         return ;
    129     }
    130 
    131     da(a, sa, n+1, 30);
    132     calheight(a, sa, n);
    133 
    134     int l = 1, r = n, mid;
    135     int ans = 0, ansp;
    136 
    137     while (l <= r) {
    138         mid = (l + r) >> 1;
    139         if (judge(mid, n)) {
    140             ans = mid;
    141             ansp = rpos;
    142             l = mid + 1;
    143         } else {
    144             r = mid - 1;
    145         }
    146     }
    147 
    148     if (ans)
    149         printf("%d %d
    ", ans, ansp);
    150     else
    151         puts("none");
    152 }
    153 
    154 int main() {
    155     ios::sync_with_stdio(false);
    156     #ifndef ONLINE_JUDGE
    157         freopen("data.in", "r", stdin);
    158         freopen("data.out", "w", stdout);
    159     #endif
    160 
    161     while (scanf("%d", &m)!=EOF && m) {
    162         scanf("%s", s);
    163         solve();
    164     }
    165 
    166     #ifndef ONLINE_JUDGE
    167         printf("time = %d.
    ", (int)clock());
    168     #endif
    169 
    170     return 0;
    171 }

    (2)哈希

      1 /* 4080 */
      2 #include <iostream>
      3 #include <sstream>
      4 #include <string>
      5 #include <map>
      6 #include <queue>
      7 #include <set>
      8 #include <stack>
      9 #include <vector>
     10 #include <deque>
     11 #include <bitset>
     12 #include <algorithm>
     13 #include <cstdio>
     14 #include <cmath>
     15 #include <ctime>
     16 #include <cstring>
     17 #include <climits>
     18 #include <cctype>
     19 #include <cassert>
     20 #include <functional>
     21 #include <iterator>
     22 #include <iomanip>
     23 using namespace std;
     24 //#pragma comment(linker,"/STACK:102400000,1024000")
     25 
     26 #define sti                set<int>
     27 #define stpii            set<pair<int, int> >
     28 #define mpii            map<int,int>
     29 #define vi                vector<int>
     30 #define pii                pair<int,int>
     31 #define vpii            vector<pair<int,int> >
     32 #define rep(i, a, n)     for (int i=a;i<n;++i)
     33 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
     34 #define clr                clear
     35 #define pb                 push_back
     36 #define mp                 make_pair
     37 #define fir                first
     38 #define sec                second
     39 #define all(x)             (x).begin(),(x).end()
     40 #define SZ(x)             ((int)(x).size())
     41 #define lson            l, mid, rt<<1
     42 #define rson            mid+1, r, rt<<1|1
     43 
     44 #define ULL unsigned __int64
     45 
     46 const int MOD = 754283;
     47 const int maxn = 40005;
     48 ULL H[maxn], base[maxn];
     49 ULL Hash[maxn];
     50 int pos[maxn];
     51 char s[maxn];
     52 int c[26];
     53 int m, len;
     54 int rp;
     55 
     56 void init() {
     57     base[0] = 1;
     58     rep(i, 1, maxn)
     59         base[i] = base[i-1] * MOD;
     60 }
     61 
     62 bool comp(const int& a, const int& b) {
     63     if (Hash[a] == Hash[b])
     64         return a<b;
     65     return Hash[a] < Hash[b];
     66 }
     67 
     68 bool judge(int l) {
     69     int n = len - l + 1;
     70     for (int i=0; i<n; ++i) {
     71         pos[i] = i;
     72         Hash[i] = H[i] - H[i+l] * base[l];
     73     }
     74 
     75     sort(pos, pos+n, comp);
     76 
     77     int i = 0;
     78     rp = -1;
     79     while (i < n) {
     80         int j = i++;
     81         while (i<n && Hash[pos[i]]==Hash[pos[j]])
     82             ++i;
     83         if (i-j >= m)
     84             rp = max(rp, pos[i-1]);
     85     }
     86 
     87     return rp >= 0;
     88 }
     89 
     90 void solve() {
     91     len = strlen(s) ;
     92 
     93     memset(c, 0, sizeof(c));
     94     rep(i, 0, len)
     95         ++c[s[i]-'a'];
     96     H[len] = 0;
     97     per(i, 0, len)
     98         H[i] = H[i+1] * MOD + s[i]-'a';
     99 
    100     bool flag = false;
    101 
    102     rep(i, 0, 26) {
    103         if (c[i] >= m) {
    104             flag = true;
    105             break;
    106         }
    107     }
    108 
    109     if (!flag) {
    110         puts("none");
    111         return ;
    112     }
    113 
    114     int ans = 1, ansp = -1;
    115     int l = 1, r = len, mid;
    116 
    117     while (l <= r) {
    118         mid = (l + r) >> 1;
    119         if (judge(mid)) {
    120             ans = mid;
    121             ansp = rp;
    122             l = mid + 1;
    123         } else {
    124             r = mid - 1;
    125         }
    126     }
    127 
    128     printf("%d %d
    ", ans, ansp);
    129 }
    130 
    131 int main() {
    132     ios::sync_with_stdio(false);
    133     #ifndef ONLINE_JUDGE
    134         freopen("data.in", "r", stdin);
    135         freopen("data.out", "w", stdout);
    136     #endif
    137 
    138     init();
    139     while (scanf("%d", &m)!=EOF && m) {
    140         scanf("%s", s);
    141         solve();
    142     }
    143 
    144 
    145     #ifndef ONLINE_JUDGE
    146         printf("time = %d.
    ", (int)clock());
    147     #endif
    148 
    149     return 0;
    150 }
  • 相关阅读:
    div+css 遮罩层
    高可用开源方案Heartbeat vs Keepalived
    nginx+keepalive 实现高可用负载均衡方案
    KeepAlive详解
    (转)高可用可伸缩架构实用经验谈 ---- 重要
    OpenStack与KVM的区别与联系
    架构师于小波:魅族实时消息推送架构
    抛开flash,自己开发实现C++ RTMP直播流播放器
    (转)C++实现RTMP协议发送H.264编码及AAC编码的音视频,摄像头直播
    (转)OC学习笔记 @property的属性 strong 和 weak 理解
  • 原文地址:https://www.cnblogs.com/bombe1013/p/5285611.html
Copyright © 2020-2023  润新知