POJ 3294 後綴數組+單調棧 || POJ 2758 後綴數組

POJ-3294 後綴數組+單調棧

鏈接:here
題意就是有n(100)n(100)個字符串,每個字符串長度不超過10001000, 求最長的一些子串,他們的出現次數超過字符串個數的一半。
aim=n/2+1aim = n/2+1,按題目要求知道這個字符串肯定是至少aimaim個連續的sa[i]sa[i]lcplcp
維護一個棧,記錄棧裏面屬於不同編號的後綴的數量,一旦達到aimaim個,就求一下他們的lcplcp,取maxmax
然後移動左端點,直到不同編號的後綴數量小於aimaim
還有就是當棧裏面lcplcp大小爲00時,也要移動左端點。

因爲height[i]height[i]表示的是Suf(sa[i1])Suf(sa[i-1])Suf(sa[i])Suf(sa[i])lcplcp,單調棧的時候加入第ii個貢獻和移除第ii個貢獻的時候會有一個麻煩。。。
索性就把板子裏的RMQquery(l,r)RMQ_query(l,r)的意思改了下。。。
反正改bugbug改了好久好久,有一點點細節吧。。。

DC3

#pragma comment(linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<map>
#include<iostream>
#include<assert.h>
#include <algorithm>

#define fi first
#define se second
#define endl '\n'
#define o2(x) (x)*(x)
#define BASE_MAX 62
#define mk make_pair
#define eb push_back
#define all(x) (x).begin(), (x).end()
#define clr(a,b) memset((a),(b),sizeof((a)))
#define iis std::ios::sync_with_stdio(false); cin.tie(0)
#define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
using namespace std;
#pragma optimize("-O3")
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, int> pLi;
inline LL read(){
    LL x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x=f?-x:x;
}
inline void write(LL x) {
    if(x==0){putchar('0'),putchar('\n');return;}
    if(x < 0) {putchar('-');x=-x;}
    static char s[23];int l = 0;
    while(x!=0)s[l++]=x%10+48,x/=10;
    while(l)putchar(s[--l]);
    putchar('\n');
}
int lowbit(int x) {return x&(-x);}
template<class T> T big(const T& a1,const T& a2) { return a1>a2?a1:a2; }
//template<typename T, typename ...R> T big (const T& f,const R& ...r) { return big(f, big (r...)); }
template<class T> T sml(const T& a1,const T& a2) { return a1<a2?a1:a2; }
//template<typename T, typename ...R> T sml (const T& f,const R& ...r) { return sml(f, sml (r...)); }
#ifndef ONLINE_JUDGE
void debug_out() { cerr << '\n'; }
template<typename T, typename ...R> void debug_out (const T& f,const R& ...r) { cerr << f << " "; debug_out (r...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
#endif
#define print(x) write(x);

#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int HMOD[] = {1000000009, 1004535809};
const LL BASE[] = {1572872831, 1971536491};
const int mod = 1e9 + 6;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MXN = 5e5 + 7;
const int N =3e5+5;
int sa[N * 3], height[N], Rank[N];;
int wa[N], wb[N], wv[N], c[N];
int dp[N][24];

int c0(int *r, int a, int b) {
    return r[a] == r[b] && r[a + 1] == r[b + 1] && r[a + 2] == r[b + 2];
}
int c12(int k, int *r, int a, int b) {
    if (k == 2) return r[a] < r[b] || r[a] == r[b] && c12(1, r, a + 1, b + 1);
    else return r[a] < r[b] || r[a] == r[b] && wv[a + 1] < wv[b + 1];
}
void _sort(int *r, int *a, int *b, int n, int m) {
    int i;
    for (i = 0; i < n; i++) wv[i] = r[a[i]];
    for (i = 0; i < m; i++) c[i] = 0;
    for (i = 0; i < n; i++) c[wv[i]]++;
    for (i = 1; i < m; i++) c[i] += c[i - 1];
    for (i = n - 1; i >= 0; i--) b[--c[wv[i]]] = a[i];
    return;
}
void dc3(int *r,int *sa,int n,int m) {
    int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
    r[n]=r[n+1]=0;
    for(i=0; i<n; i++) if(i%3!=0) wa[tbc++]=i;
    _sort(r+2,wa,wb,tbc,m);
    _sort(r+1,wb,wa,tbc,m);
    _sort(r,wa,wb,tbc,m);
    for(p=1,rn[F(wb[0])]=0,i=1; i<tbc; i++)
        rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
    if(p<tbc) dc3(rn,san,tbc,p);
    else for(i=0; i<tbc; i++) san[rn[i]]=i;
    for(i=0; i<tbc; i++) if(san[i]<tb) wb[ta++]=san[i]*3;
    if(n%3==1) wb[ta++]=n-1;
    _sort(r,wb,wa,ta,m);
    for(i=0; i<tbc; i++) wv[wb[i]=G(san[i])]=i;
    for(i=0,j=0,p=0; i<ta && j<tbc; p++)
        sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
    for(; i<ta; p++) sa[p]=wa[i++];
    for(; j<tbc; p++) sa[p]=wb[j++];
    return;
}
void calheight(int *r, int *sa, int n) {
    int i, j, k = 0;
    for (i = 1; i <= n; i++) Rank[sa[i]] = i;
    for (i = 0; i < n; height[Rank[i++]] = k)
        for (k ? k-- : 0, j = sa[Rank[i] - 1]; r[i + k] == r[j + k]; k++);
}
//LCP(suffix(i), suffix(j))=RMQ_query(rnk[i], rnk[j]);
int RMQ_query(int l, int r) {
    l = Rank[l]; r = Rank[r];
//    if(l == r) return dp[l][0];
    if (l > r) swap(l, r);
//    l++;
    int k = 0; while (1<<(k+1) <= r - l + 1) k++;
    return min(dp[l][k], dp[r-(1<<k)+1][k]);
}
void RMQ_init(int n) {
    for (int i=0; i<n; ++i) dp[i][0] = height[i];
    for (int j=1; (1<<j)<=n; ++j) {
        for (int i=0; i+(1<<j)-1<n; ++i) {
            dp[i][j] = std::min (dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
        }
    }
}
int n, m;
int k;
int id[MXN], vis[MXN];
char ar[MXN], br[MXN], cr[MXN];
int s[MXN];
int stak[MXN], top;
int main() {
#ifndef ONLINE_JUDGE
    freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
    //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
    while(~scanf("%d", &k) && k) {
        scanf("%s", ar);
        for(int i = 0; i <= k; ++i) vis[i] = 0;
        int len = strlen(ar);
        memcpy(cr, ar, len);
        int Max = 128;
        for(int i = 0; i < len; ++i) id[i] = 1, s[i] = ar[i];
        for(int i = 1; i < k; ++i) {
            scanf("%s", br);
            s[len] = 'z' + i;ar[len] = 'z' + 1;
            Max = big(Max, 'z' + i);
            id[len] = 0;
            int tmp = strlen(br);
            for(int j = 0; j < tmp; ++j) id[len + j + 1] = i + 1, s[len+j+1] = br[j];
            memcpy(ar + len + 1, br, tmp);
            len += tmp + 1;
        }
        if(k == 1) {
            printf("%s\n", ar);
            printf("\n");
            continue;
        }
        ar[len] = '\0';
        s[len] = '\0';
        dc3(s, sa, len + 1, 256);
        calheight(s, sa, len);
        RMQ_init(len+1);
        top = 0;
        int ans = 0, cnt = 1, aim = k/2 + 1, l = 1;
        ++ vis[id[ sa[1]]];
        for(int i = 2; i <= len; ++i) {
            if(vis[id[ sa[i]]] == 0 && id[ sa[i]]) ++ cnt;
            ++ vis[id[ sa[i]]];
            if(cnt >= aim) {
                int tmp =  RMQ_query( sa[l+1],  sa[i]);
                if(tmp > ans) {
                    ans = tmp;
                    top = 0;
                    stak[++top] = i;
                }else if(tmp == ans && ans) {
                    stak[++top] = i;
                }
            }
            while(l < i &&  RMQ_query( sa[l+1],  sa[i]) == 0) {
                -- vis[id[ sa[l]]];
                if(id[ sa[l]] && vis[id[ sa[l]]] == 0) -- cnt;
                ++ l;
                if(cnt >= aim) {
                    int tmp =  RMQ_query( sa[l+1],  sa[i]);
                    if(tmp > ans) {
                        ans = tmp;
                        top = 0;
                        stak[++top] = i;
                    }else if(tmp == ans && ans) {
                        stak[++top] = i;
                    }
                }
            }
            while(cnt >= aim && l < i) {
                -- vis[id[ sa[l]]];
                if(id[ sa[l]] && vis[id[ sa[l]]] == 0) -- cnt;
                ++ l;
                if(cnt >= aim) {
                    int tmp =  RMQ_query( sa[l+1],  sa[i]);
                    if(tmp > ans) {
                        ans = tmp;
                        top = 0;
                        stak[++top] = i;
                    }else if(tmp == ans && ans) {
                        stak[++top] = i;
                    }
                }
            }
        }
        for(int i = 0; i <= len; ++i) id[i] = s[i] = 0;
        if(ans <= 0) printf("?\n");
        else {
            vector<string> vs;
            for(int i = 1; i <= top; ++i) {
                string tmp = "";
                for(int j =  sa[stak[i]], h = 0; h < ans; ++h, ++j) tmp += ar[j];
                vs.eb(tmp);
            }
            my_unique(vs);
            for(int i = 0; i < vs.size(); ++i) {
                for(int j = 0; j < ans; ++j) ar[j] = vs[i][j]; ar[ans] = '\0';
                printf("%s\n", ar);
            }
        }
        printf("\n");
    }
#ifndef ONLINE_JUDGE
    cout << "time cost:" << clock() << "ms" << endl;
#endif
    return 0;
}

倍增

#pragma comment(linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<map>
#include<iostream>
#include<assert.h>
#include <algorithm>

#define fi first
#define se second
#define endl '\n'
#define o2(x) (x)*(x)
#define BASE_MAX 62
#define mk make_pair
#define eb push_back
#define all(x) (x).begin(), (x).end()
#define clr(a,b) memset((a),(b),sizeof((a)))
#define iis std::ios::sync_with_stdio(false); cin.tie(0)
#define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
using namespace std;
#pragma optimize("-O3")
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, int> pLi;
inline LL read(){
    LL x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x=f?-x:x;
}
inline void write(LL x) {
    if(x==0){putchar('0'),putchar('\n');return;}
    if(x < 0) {putchar('-');x=-x;}
    static char s[23];int l = 0;
    while(x!=0)s[l++]=x%10+48,x/=10;
    while(l)putchar(s[--l]);
    putchar('\n');
}
int lowbit(int x) {return x&(-x);}
template<class T> T big(const T& a1,const T& a2) { return a1>a2?a1:a2; }
//template<typename T, typename ...R> T big (const T& f,const R& ...r) { return big(f, big (r...)); }
template<class T> T sml(const T& a1,const T& a2) { return a1<a2?a1:a2; }
//template<typename T, typename ...R> T sml (const T& f,const R& ...r) { return sml(f, sml (r...)); }
#ifndef ONLINE_JUDGE
void debug_out() { cerr << '\n'; }
template<typename T, typename ...R> void debug_out (const T& f,const R& ...r) { cerr << f << " "; debug_out (r...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
#endif
#define print(x) write(x);

const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int HMOD[] = {1000000009, 1004535809};
const LL BASE[] = {1572872831, 1971536491};
const int mod = 1e9 + 6;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MXN = 2e5 + 7;

struct Suffix_Array {
    static const int N = 2e5 + 7;
    int n, len, s[N], M;
    int sa[N], rnk[N], height[N];
    int tmp_one[N], tmp_two[N], c[N];
    int dp[N][24];
    void init_str(int *str, int _n) {
        len = _n;
        n = len + 1;
        for (int i = 0; i < len; ++i) {
            s[i] = str[i];
        }
        s[len] = '\0';
    }
    void build_sa(int m = 128);
    void calc_height(int n);
    void Out(char *str);
    void RMQ_init(int n);
    int RMQ_query(int l, int r);
    int cmp_suffix(char* pattern, int p){//判斷是否爲後綴p的前綴
        return strncmp(pattern, reinterpret_cast<const char *>(s + sa[p]), M);
    }
    int find(char* P){//Omlog(n)
        M = strlen(P);
        if(cmp_suffix(P, 0) < 0) return -1;
        if(cmp_suffix(P, n-1) > 0) return -1;
        int L = 0, R = n - 1;
        while(R >= L){
            int mid = L + (R - L) / 2;
            int res = cmp_suffix(P, mid);
            if(!res) return mid;
            if(res < 0) R = mid - 1; else L = mid + 1;
        }
        return -1;
    }
}SA;
void Suffix_Array::Out(char *str) {
    puts ("/*Suffix*/");
    for (int i=0; i<n; ++i) {
        printf ("%s\n", str+sa[i]);
    }
}
//LCP(suffix(i), suffix(j))=RMQ_query(rnk[i], rnk[j]);
int Suffix_Array::RMQ_query(int l, int r) {
    l = rnk[l]; r = rnk[r];
//    if(l == r) return dp[l][0];
    if (l > r) swap(l, r);
//    l++;
    int k = 0; while (1<<(k+1) <= r - l + 1) k++;
    return min(dp[l][k], dp[r-(1<<k)+1][k]);
}
void Suffix_Array::RMQ_init(int n) {
    for (int i=0; i<n; ++i) dp[i][0] = height[i];
    for (int j=1; (1<<j)<=n; ++j) {
        for (int i=0; i+(1<<j)-1<n; ++i) {
            dp[i][j] = std::min (dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
        }
    }
}
void Suffix_Array::calc_height(int n) {
    for (int i=0; i<=n; ++i) rnk[sa[i]] = i;
    int k = height[0] = 0;
    for (int i=0; i<n; ++i) {
        if (k) k--;
        int j = sa[rnk[i]-1];
        while (s[i+k] == s[j+k]) k++;
        height[rnk[i]] = k;
    }
}
//m = max(r[i]) + 1,一般字符128足夠了
void Suffix_Array::build_sa(int m) {
    int i, j, p, *x = tmp_one, *y = tmp_two;
    for (i=0; i<m; ++i) c[i] = 0;
    for (i=0; i<n; ++i) c[x[i]=s[i]]++;
    for (i=1; i<m; ++i) c[i] += c[i-1];
    for (i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
    for (j=1; j<=n; j<<=1) {
        for (p=0, i=n-j; i<n; ++i) y[p++] = i;
        for (i=0; i<n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
        for (i=0; i<m; ++i) c[i] = 0;
        for (i=0; i<n; ++i) c[x[y[i]]]++;
        for (i=1; i<m; ++i) c[i] += c[i-1];
        for (i=n-1; i>=0; --i) sa[--c[x[y[i]]]] = y[i];
        std::swap (x, y);
        for (p=1, x[sa[0]]=0, i=1; i<n; ++i) {
            x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+j] == y[sa[i]+j] ? p - 1 : p++);
        }
        if(p >= n) break;
        m=p;
    }
    calc_height(n-1);
    RMQ_init(n);
}
int n, m;
int k;
int id[MXN], vis[MXN];
char ar[MXN], br[MXN], cr[MXN];
int s[MXN];
int stak[MXN], top;
int main() {
#ifndef ONLINE_JUDGE
    freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
    //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
    int cas = 0;
    while(~scanf("%d", &k) && k) {
        ++ cas;
        scanf("%s", ar);
        for(int i = 0; i <= k; ++i) vis[i] = 0;
        int len = strlen(ar);
        memcpy(cr, ar, len);
        int Max = 128;
        for(int i = 0; i < len; ++i) id[i] = 1, s[i] = ar[i];
        for(int i = 1; i < k; ++i) {
            scanf("%s", br);
            s[len] = 'z' + i;ar[len] = 'z' + 1;
            Max = big(Max, 'z' + i);
            id[len] = 0;
            int tmp = strlen(br);
            for(int j = 0; j < tmp; ++j) id[len + j + 1] = i + 1, s[len+j+1] = br[j];
            memcpy(ar + len + 1, br, tmp);
            len += tmp + 1;
        }
//        if(cas > 1) printf("\n");
        if(k == 1) {
            printf("%s\n", ar);
            printf("\n");
            continue;
        }
        ar[len] = '\0';
        s[len] = '\0';
//        debug(ar)
//        for(int i = 0; i < len; ++i) printf("%d ", id[i]); printf("\n");
        SA.init_str(s, len);
        SA.build_sa(Max + 1);
//        SA.Out(ar);
        top = 0;
        int ans = 0, cnt = 1, aim = k/2 + 1, l = 1;
        for(int i = 1; i <= len; ++i) {
//            printf("* %d   ", SA.height[i]);
//            printf("%c%c%c\n", ar[SA.sa[i]], ar[SA.sa[i]+1], ar[SA.sa[i]+2]);
        }
        ++ vis[id[SA.sa[1]]];
        for(int i = 2; i <= len; ++i) {
//            if(cnt == 0 && id[SA.sa[i-1]] && i != 1) ++ cnt, ++ vis[id[SA.sa[i-1]]];
            if(vis[id[SA.sa[i]]] == 0 && id[SA.sa[i]]) ++ cnt;
            ++ vis[id[SA.sa[i]]];
            if(cnt >= aim) {
                int tmp = SA.RMQ_query(SA.sa[l+1], SA.sa[i]);
                if(tmp > ans) {
                    ans = tmp;
                    top = 0;
                    stak[++top] = i;
                }else if(tmp == ans && ans) {
                    stak[++top] = i;
                }
            }
            if(i < 10) {
//                printf("%d %d %d %d %d %c%c%c\n", SA.height[i], i, l, cnt, ans, ar[SA.sa[i]], ar[SA.sa[i] + 1], ar[SA.sa[i] + 2]);
//                printf("** %d **\n", SA.RMQ_query(SA.sa[l + 1], SA.sa[i]));
            }
            while(l < i && SA.RMQ_query(SA.sa[l+1], SA.sa[i]) == 0) {
                -- vis[id[SA.sa[l]]];
                if(id[SA.sa[l]] && vis[id[SA.sa[l]]] == 0) -- cnt;
                ++ l;
                if(cnt >= aim) {
                    int tmp = SA.RMQ_query(SA.sa[l+1], SA.sa[i]);
                    if(tmp > ans) {
                        ans = tmp;
                        top = 0;
                        stak[++top] = i;
                    }else if(tmp == ans && ans) {
                        stak[++top] = i;
                    }
                }
            }
            while(cnt >= aim && l < i) {
                -- vis[id[SA.sa[l]]];
                if(id[SA.sa[l]] && vis[id[SA.sa[l]]] == 0) -- cnt;
                ++ l;
                if(cnt >= aim) {
                    int tmp = SA.RMQ_query(SA.sa[l+1], SA.sa[i]);
                    if(tmp > ans) {
                        ans = tmp;
                        top = 0;
                        stak[++top] = i;
                    }else if(tmp == ans && ans) {
                        stak[++top] = i;
                    }
                }
            }
        }
        for(int i = 0; i <= len; ++i) id[i] = s[i] = 0;
        if(ans <= 0) printf("?\n");
        else {
            vector<string> vs;
            for(int i = 1; i <= top; ++i) {
                string tmp = "";
                for(int j = SA.sa[stak[i]], h = 0; h < ans; ++h, ++j) tmp += ar[j];
                vs.eb(tmp);
            }
//            sort(all(vs));
            my_unique(vs);
            for(int i = 0; i < vs.size(); ++i) {
                for(int j = 0; j < ans; ++j) ar[j] = vs[i][j]; ar[ans] = '\0';
                printf("%s\n", ar);
            }
        }
        printf("\n");
    }
#ifndef ONLINE_JUDGE
    cout << "time cost:" << clock() << "ms" << endl;
#endif
    return 0;
}
//後綴數組(SA[i]存放排名第i大的後綴首字符的下標)
//名次數組(rank[i]存放suffix(i)的優先級(名次))
//height數組:height[i]是Suffix(sa[i-1])和Suffix(sa[i])的最長公共前綴長度
/*SA,R,H的下標都是 0~n 其中多包括了一個空字符串*/

數據

輸入:
2
adsf
asdf
2
fdsa
df
5
abcd
bcde
cdef
defg
efgh
5
nshiyedashai
goanshab
woshidiyi
firstorloser
iamthefirst
4
acaaaaaaaaaaaaa
aaaaa
aa
a
4
aa
a
d
d
2
pabcp
pertp
0

輸出:
a
d
f
s

d
f

cd
de
ef

sh

aa

?

p

題面

在這裏插入圖片描述

POJ 2758 後綴數組

aa[i]表示的是新字符串的下標i所對應的老字符串的下標
id[i]表示的是老字符串的下標i所對應的新字符串的下標
is[i] = 1 or 0:表示新字符串中i這個字符是否來自老字符串
set<int> st保存老字符串前插入了字符的下標

插入操作q1q1不超過200200;查詢操作q2q2不超過2000020000.
複雜度O(q1×q2)O(q1×q2)
若詢問(x,y)(x,y),先求出lcp(Suffix(x),Suffix(y))lcp(Suffix(x), Suffix(y)),然後通過上面幾個數組求出xxyy距右邊新字符的最近距離cmincmin
lcp&gt;cminlcp \gt cmin, 則直接返回lcplcp
反之從cmincmin長度開始往後暴力匹配,最多匹配200200次就會到達字符串邊界或者新的(x,y)(x&#x27;,y&#x27;),滿足(x,y)(x&#x27;,y&#x27;)都是原來的老字符
這樣遞歸處理即可。

SA

#pragma comment(linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<cmath>
#include<map>
#include<set>
#include<iostream>
#include<assert.h>
#include <algorithm>

#define fi first
#define se second
#define endl '\n'
#define o2(x) (x)*(x)
#define BASE_MAX 62
#define mk make_pair
#define eb push_back
#define all(x) (x).begin(), (x).end()
#define clr(a,b) memset((a),(b),sizeof((a)))
#define iis std::ios::sync_with_stdio(false); cin.tie(0)
#define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
using namespace std;
#pragma optimize("-O3")
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, int> pLi;
inline LL read(){
    LL x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x=f?-x:x;
}
inline void write(LL x) {
    if(x==0){putchar('0'),putchar('\n');return;}
    if(x < 0) {putchar('-');x=-x;}
    static char s[23];int l = 0;
    while(x!=0)s[l++]=x%10+48,x/=10;
    while(l)putchar(s[--l]);
    putchar('\n');
}
int lowbit(int x) {return x&(-x);}
template<class T> T big(const T& a1,const T& a2) { return a1>a2?a1:a2; }
//template<typename T, typename ...R> T big (const T& f,const R& ...r) { return big(f, big (r...)); }
template<class T> T sml(const T& a1,const T& a2) { return a1<a2?a1:a2; }
//template<typename T, typename ...R> T sml (const T& f,const R& ...r) { return sml(f, sml (r...)); }
#ifndef ONLINE_JUDGE
void debug_out() { cerr << '\n'; }
template<typename T, typename ...R> void debug_out (const T& f,const R& ...r) { cerr << f << " "; debug_out (r...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
#endif
#define print(x) write(x);

const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int HMOD[] = {1000000009, 1004535809};
const LL BASE[] = {1572872831, 1971536491};
const int mod = 1e9 + 6;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MXN = 3e5 + 7;

struct Suffix_Array {
    static const int N = 3e5 + 7;
    int n, len, s[N], M;
    int sa[N], rnk[N], height[N];
    int tmp_one[N], tmp_two[N], c[N];
    int dp[N][21];
    void init_str(int *str, int _n) {
        len = _n;
        n = len + 1;
        for (int i = 0; i < len; ++i) {
            s[i] = str[i];
        }
        s[len] = '\0';
    }
    void build_sa(int m = 128);
    void calc_height(int n);
    void Out(char *str);
    void RMQ_init(int n);
    int RMQ_query(int l, int r);
    int cmp_suffix(char* pattern, int p){//判斷是否爲後綴p的前綴
        return strncmp(pattern, reinterpret_cast<const char *>(s + sa[p]), M);
    }
    int find(char* P){//Omlog(n)
        M = strlen(P);
        if(cmp_suffix(P, 0) < 0) return -1;
        if(cmp_suffix(P, n-1) > 0) return -1;
        int L = 0, R = n - 1;
        while(R >= L){
            int mid = L + (R - L) / 2;
            int res = cmp_suffix(P, mid);
            if(!res) return mid;
            if(res < 0) R = mid - 1; else L = mid + 1;
        }
        return -1;
    }
}SA;
void Suffix_Array::Out(char *str) {
    puts ("/*Suffix*/");
    for (int i=0; i<n; ++i) {
        printf ("%s\n", str+sa[i]);
    }
}
int Suffix_Array::RMQ_query(int l, int r) {
    l = rnk[l]; r = rnk[r];
    if (l > r) swap(l, r);
    l++;
    int k = 0; while (1<<(k+1) <= r - l + 1) k++;
    return min(dp[l][k], dp[r-(1<<k)+1][k]);
}
void Suffix_Array::RMQ_init(int n) {
    for (int i=0; i<n; ++i) dp[i][0] = height[i];
    for (int j=1; (1<<j)<=n; ++j) {
        for (int i=0; i+(1<<j)-1<n; ++i) {
            dp[i][j] = std::min (dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
        }
    }
}
void Suffix_Array::calc_height(int n) {
    for (int i=0; i<=n; ++i) rnk[sa[i]] = i;
    int k = height[0] = 0;
    for (int i=0; i<n; ++i) {
        if (k) k--;
        int j = sa[rnk[i]-1];
        while (s[i+k] == s[j+k]) k++;
        height[rnk[i]] = k;
    }
}
//m = max(r[i]) + 1,一般字符128足夠了
void Suffix_Array::build_sa(int m) {
    int i, j, p, *x = tmp_one, *y = tmp_two;
    for (i=0; i<m; ++i) c[i] = 0;
    for (i=0; i<n; ++i) c[x[i]=s[i]]++;
    for (i=1; i<m; ++i) c[i] += c[i-1];
    for (i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
    for (j=1; j<=n; j<<=1) {
        for (p=0, i=n-j; i<n; ++i) y[p++] = i;
        for (i=0; i<n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
        for (i=0; i<m; ++i) c[i] = 0;
        for (i=0; i<n; ++i) c[x[y[i]]]++;
        for (i=1; i<m; ++i) c[i] += c[i-1];
        for (i=n-1; i>=0; --i) sa[--c[x[y[i]]]] = y[i];
        std::swap (x, y);
        for (p=1, x[sa[0]]=0, i=1; i<n; ++i) {
            x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+j] == y[sa[i]+j] ? p - 1 : p++);
        }
        if(p >= n) break;
        m=p;
    }
    calc_height(n-1);
    RMQ_init(n);
}
int n, m;
int k;
int id[MXN], is[MXN], aa[MXN];
char ar[MXN];
int s[MXN];
set<int> st;
/*
aa[i]表示的是新字符串的下標i所對應的老字符串的下標
id[i]表示的是老字符串的下標i所對應的新字符串的下標
is[i] = 1 or 0:表示新字符串中i這個字符是否來自老字符串
set<int> st保存老字符串前插入了字符的下標

插入操作q1不超過200;查詢操作q2不超過20000.
複雜度O(q1×q2)
若詢問(x,y),先求出lcp(Suffix(x), Suffix(y)),然後通過上面幾個數組求出x和y距右邊新字符的最近距離cmin
若lcp > cmin, 則直接返回lcp
反之從cmin長度開始往後暴力匹配,最多匹配200次就會到達字符串邊界或者新的(x',y'),滿足(x',y')都是原來的老字符
這樣遞歸處理即可。
*/
int check(int x, int y) {
    if(x > y) swap(x, y);
    int lcp = SA.RMQ_query(x, y);
    if(st.size() == 0) return lcp;
    int lx = *st.lower_bound(x+1), ly = *st.lower_bound(y+1);
//    debug(x, y, lcp, lx, ly)
    int cmin = INF, len = 0;
    if(lx > x) cmin = id[lx-1] - id[x] + 1, len = id[lx] - (lx!=0?id[lx-1]:0);
    if(ly > y) cmin = sml(cmin, id[ly-1] - id[y] + 1), len = big(len, id[ly] - (ly!=0?id[ly-1]:0));
    if(cmin > lcp) return lcp;
//    debug(cmin, len)
    len = 201;
    for(int i = 1; i <= len; ++i) {
//        debug(id[x] + i + cmin - 1, id[y] + i + cmin - 1, s[id[x] + i + cmin - 1] != s[id[y] + i + cmin - 1])
        if(s[id[x] + i + cmin - 1] != s[id[y] + i + cmin - 1]) {
            return cmin - 1 + i;
        }
        if(id[y] + i + cmin - 1 == n-1) return cmin + i;
        if(is[id[x] + i + cmin - 1] && is[id[y] + i + cmin - 1]) {
//            debug(i + cmin - 1, aa[id[x] + i + cmin - 1], aa[id[y] + i + cmin - 1])
            return check(aa[id[x] + i + cmin - 1], aa[id[y] + i + cmin - 1]) + i + cmin - 1;
        }
    }
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
    //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
    scanf("%s", ar);
        scanf("%d", &k);
        m = n = strlen(ar);
        for(int i = 0; i < n; ++i) s[i] = ar[i], aa[i] = id[i] = i, is[i] = 1;
        aa[n] = id[n] = n;
        SA.init_str(s, n);
        SA.build_sa(128);
        char op[2];
        while(k --) {
            scanf("%s", op);
            int l, r;
            if(op[0] == 'Q') {
                scanf("%d%d", &l, &r);
                if(l == r) printf("%d\n", n - id[l-1]);
                else printf("%d\n", check(l - 1, r - 1));
            }else {
                scanf("%s%d", op, &r);
                if(r > n) r = n + 1;
                for (int i = n; i > r - 1; --i) s[i] = s[i - 1], is[i] = is[i-1], aa[i] = aa[i-1];
                s[r - 1] = op[0]; is[r-1] = 0;
//                aa[r - l] = aa[r];
                if(r > n) st.insert(m);
                else st.insert(aa[r]);
                id[m] = n;
                ++ n;
                for(int i = r; i <= n; ++i) if(is[i]) id[aa[i]] = i;
            }
        }
#ifndef ONLINE_JUDGE
    cout << "time cost:" << clock() << "ms" << endl;
#endif
    return 0;
}
//後綴數組(SA[i]存放排名第i大的後綴首字符的下標)
//名次數組(rank[i]存放suffix(i)的優先級(名次))
//height數組:height[i]是Suffix(sa[i-1])和Suffix(sa[i])的最長公共前綴長度
/*SA,R,H的下標都是 0~n 其中多包括了一個空字符串*/

DC3

#pragma comment(linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<map>
#include<iostream>
#include<assert.h>
#include <algorithm>
#include "set"
#define fi first
#define se second
#define endl '\n'
#define o2(x) (x)*(x)
#define BASE_MAX 62
#define mk make_pair
#define eb push_back
#define all(x) (x).begin(), (x).end()
#define clr(a,b) memset((a),(b),sizeof((a)))
#define iis std::ios::sync_with_stdio(false); cin.tie(0)
#define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
using namespace std;
#pragma optimize("-O3")
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, int> pLi;
inline LL read(){
    LL x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x=f?-x:x;
}
inline void write(LL x) {
    if(x==0){putchar('0'),putchar('\n');return;}
    if(x < 0) {putchar('-');x=-x;}
    static char s[23];int l = 0;
    while(x!=0)s[l++]=x%10+48,x/=10;
    while(l)putchar(s[--l]);
    putchar('\n');
}
int lowbit(int x) {return x&(-x);}
template<class T> T big(const T& a1,const T& a2) { return a1>a2?a1:a2; }
//template<typename T, typename ...R> T big (const T& f,const R& ...r) { return big(f, big (r...)); }
template<class T> T sml(const T& a1,const T& a2) { return a1<a2?a1:a2; }
//template<typename T, typename ...R> T sml (const T& f,const R& ...r) { return sml(f, sml (r...)); }
#ifndef ONLINE_JUDGE
void debug_out() { cerr << '\n'; }
template<typename T, typename ...R> void debug_out (const T& f,const R& ...r) { cerr << f << " "; debug_out (r...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
#endif
#define print(x) write(x);

#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int HMOD[] = {1000000009, 1004535809};
const LL BASE[] = {1572872831, 1971536491};
const int mod = 1e9 + 6;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MXN = 5e5 + 7;
const int N = 1e6 + 5;

struct DC3 {
    static const int N = 1e6 + 5;
    int sa[N * 3], height[N], rnk[N];;
    int wa[N], wb[N], wv[N], c[N];
    int dp[N][24];
    int c0(int *r, int a, int b) {
        return r[a] == r[b] && r[a + 1] == r[b + 1] && r[a + 2] == r[b + 2];
    }
    int c12(int k, int *r, int a, int b) {
        if (k == 2) return r[a] < r[b] || r[a] == r[b] && c12(1, r, a + 1, b + 1);
        else return r[a] < r[b] || r[a] == r[b] && wv[a + 1] < wv[b + 1];
    }
    void _sort(int *r, int *a, int *b, int n, int m) {
        int i;
        for (i = 0; i < n; i++) wv[i] = r[a[i]];
        for (i = 0; i < m; i++) c[i] = 0;
        for (i = 0; i < n; i++) c[wv[i]]++;
        for (i = 1; i < m; i++) c[i] += c[i - 1];
        for (i = n - 1; i >= 0; i--) b[--c[wv[i]]] = a[i];
        return;
    }
    //dc3.dc3(s, dc3.sa, len + 1, 256);
    //dc3.calheight(s, len);
    void dc3(int *r, int *sa, int n, int m) {
        int i, j, *rn = r + n, *san = sa + n, ta = 0, tb = (n + 1) / 3, tbc = 0, p;
        r[n] = r[n + 1] = 0;
        for (i = 0; i < n; i++) if (i % 3 != 0) wa[tbc++] = i;
        _sort(r + 2, wa, wb, tbc, m);
        _sort(r + 1, wb, wa, tbc, m);
        _sort(r, wa, wb, tbc, m);
        for (p = 1, rn[F(wb[0])] = 0, i = 1; i < tbc; i++)
            rn[F(wb[i])] = c0(r, wb[i - 1], wb[i]) ? p - 1 : p++;
        if (p < tbc) dc3(rn, san, tbc, p);
        else for (i = 0; i < tbc; i++) san[rn[i]] = i;
        for (i = 0; i < tbc; i++) if (san[i] < tb) wb[ta++] = san[i] * 3;
        if (n % 3 == 1) wb[ta++] = n - 1;
        _sort(r, wb, wa, ta, m);
        for (i = 0; i < tbc; i++) wv[wb[i] = G(san[i])] = i;
        for (i = 0, j = 0, p = 0; i < ta && j < tbc; p++)
            sa[p] = c12(wb[j] % 3, r, wa[i], wb[j]) ? wa[i++] : wb[j++];
        for (; i < ta; p++) sa[p] = wa[i++];
        for (; j < tbc; p++) sa[p] = wb[j++];
        return;
    }
    void calheight(int *r, int n) {
        int i, j, k = 0;
        for (i = 1; i <= n; i++) rnk[sa[i]] = i;
        for (i = 0; i < n; height[rnk[i++]] = k)
            for (k ? k-- : 0, j = sa[rnk[i] - 1]; r[i + k] == r[j + k]; k++);
        RMQ_init(n + 1);
    }
    int RMQ_query(int l, int r) {
        l = rnk[l], r = rnk[r];
//    if(l == r) return dp[l][0];
        if (l > r) swap(l, r);
        l++;
        int k = 0;
        while (1 << (k + 1) <= r - l + 1) k++;
        return min(dp[l][k], dp[r - (1 << k) + 1][k]);
    }
    void RMQ_init(int n) {
        for (int i = 0; i < n; ++i) dp[i][0] = height[i];
        for (int j = 1; (1 << j) <= n; ++j) {
            for (int i = 0; i + (1 << j) - 1 < n; ++i) {
                dp[i][j] = std::min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
            }
        }
    }
}dc3;


int n, m;
int k;
int id[MXN], is[MXN], aa[MXN];
char ar[MXN];
int s[MXN];
set<int> st;
int check(int x, int y) {
    if(x > y) swap(x, y);
    int lcp = dc3.RMQ_query(x, y);
    if(st.size() == 0) return lcp;
    int lx = *st.lower_bound(x+1), ly = *st.lower_bound(y+1);
//    debug(x, y, lcp, lx, ly)
    int cmin = INF, len = 0;
    if(lx > x) cmin = id[lx-1] - id[x] + 1, len = id[lx] - (lx!=0?id[lx-1]:0);
    if(ly > y) cmin = sml(cmin, id[ly-1] - id[y] + 1), len = big(len, id[ly] - (ly!=0?id[ly-1]:0));
    if(cmin > lcp) return lcp;
//    debug(cmin, len)
    for(int i = 1; i <= 201; ++i) {
//        debug(id[x] + i + cmin - 1, id[y] + i + cmin - 1, s[id[x] + i + cmin - 1] != s[id[y] + i + cmin - 1])
        if(s[id[x] + i + cmin - 1] != s[id[y] + i + cmin - 1]) {
            return cmin - 1 + i;
        }
        if(id[y] + i + cmin - 1 == n-1) return cmin + i;
        if(is[id[x] + i + cmin - 1] && is[id[y] + i + cmin - 1]) {
//            debug(i + cmin - 1, aa[id[x] + i + cmin - 1], aa[id[y] + i + cmin - 1])
            return check(aa[id[x] + i + cmin - 1], aa[id[y] + i + cmin - 1]) + i + cmin - 1;
        }
    }
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
    //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
    scanf("%s", ar);
    scanf("%d", &k);
    m = n = strlen(ar);
    for(int i = 0; i < n; ++i) s[i] = ar[i], aa[i] = id[i] = i, is[i] = 1;
    aa[n] = id[n] = n;
    dc3.dc3(s, dc3.sa, n + 1, 256);
    dc3.calheight(s, n);
    char op[2];
    while(k --) {
        scanf("%s", op);
        int l, r;
        if(op[0] == 'Q') {
            scanf("%d%d", &l, &r);
            if(l == r) printf("%d\n", n - id[l-1]);
            else printf("%d\n", check(l - 1, r - 1));
        }else {
            scanf("%s%d", op, &r);
            if(r > n) r = n + 1;
            for (int i = n; i > r - 1; --i) s[i] = s[i - 1], is[i] = is[i-1], aa[i] = aa[i-1];
            s[r - 1] = op[0]; is[r-1] = 0;
//                aa[r - l] = aa[r];
            if(r > n) st.insert(m);
            else st.insert(aa[r]);
            id[m] = n;
            ++ n;
            for(int i = r; i <= n; ++i) if(is[i]) id[aa[i]] = i;
        }
    }
#ifndef ONLINE_JUDGE
    cout << "time cost:" << clock() << "ms" << endl;
#endif
    return 0;
}
//後綴數組(SA[i]存放排名第i大的後綴首字符的下標)
//名次數組(rank[i]存放suffix(i)的優先級(名次))
//height數組:height[i]是Suffix(sa[i-1])和Suffix(sa[i])的最長公共前綴長度
/*SA,R,H的下標都是 0~n 其中多包括了一個空字符串*/

題面

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章