POJ 1743 Musical ThemeSAM

Posted kikokiko

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1743 Musical ThemeSAM相关的知识,希望对你有一定的参考价值。

POJ1743 Musical Theme

要找长度(ge 5)且出现次数(ge 2)并且第一次出现和最后一次出现不重叠的最长子串。
题目条件中,如果对于两个串,在一个串的每个数上都加上相同的数之后可以得到另一个串,那么这个两个串可以被是相同的。
首先我们先得到差分数组,然后要求的就是差分数组中长度(ge 4)且出现次数(ge 2)并且第一次出现和最后一次出现不重叠的最长子串
我们需要知道的是每个等价类中终点的最左端和最右端的位置,即((firstpos,lastpos)),每次新加入一个字符所得到的等价类其(firstpos)(lastpos)必然为当前的下标,当构造完(SAM)之后,由于(parent)树的性质,(link[u])所表示的等价类必然是(u)所表示的等价类的后缀,所以可以得到:(lastpos[u] = max_{vin children} lastpos[v])其中(v)(u)(parent)树中的儿子,而(firstpos)必然一直保持不变。
可以用拓扑排序然后倒序遍历来代替建(parent)树然后(dfs),拓扑排序即为按(len)排序,用基数排序即可

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<string>
#include<algorithm>
#include<stack>
using namespace std;
void ____(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); }
const int MAXN = 1e5+7;
int n,A[MAXN];
struct SAM{
    int len[MAXN],link[MAXN],firstpos[MAXN],lastpos[MAXN],ch[MAXN][180],tot,last,cnt[MAXN],c[MAXN],sa[MAXN];
    void init(){ link[tot = last = cnt[0] = len[0] = 0] = -1; memset(ch[0],0,sizeof(ch[0])); }
    void extend(int x){
        int np = ++tot, p = last; firstpos[tot] = lastpos[tot] = len[tot] = len[last] + 1;
        memset(ch[tot],0,sizeof(ch[tot])); cnt[tot] = 1;
        while(p!=-1 and !ch[p][x]){
            ch[p][x] = np;
            p = link[p];
        }
        if(p==-1) link[np] = 0;
        else{
            int q = ch[p][x];
            if(len[p]+1==len[q]) link[np] = q;
            else{
                int clone = ++tot;
                cnt[clone] = 0;
                firstpos[clone] = firstpos[q];
                lastpos[clone] = lastpos[q];
                len[clone] = len[p] + 1;
                for(int i = 0; i < 180; i++) ch[clone][i] = ch[q][i];
                link[clone] = link[q];
                while(p!=-1 and ch[p][x]==q){
                    ch[p][x] = clone;
                    p = link[p];
                }
                link[np] = link[q] = clone;
            }
        }
        last = np;
    }
    int solve(){
        for(int i = 0; i <= n; i++) c[i] = 0;
        for(int i = 0; i <= tot; i++) c[len[i]]++;
        for(int i = 1; i <= n; i++) c[i] += c[i-1];
        for(int i = tot; i >= 0; i--) sa[c[len[i]]--] = i;
        int ret = 0;
        for(int i = tot+1; i >= 1; i--){            //这里要注意,基数排序的时候是0~tot,所以排名最后的是tot+1
            int u = sa[i];
            cnt[link[u]] += cnt[u];
            lastpos[link[u]] = max(lastpos[link[u]],lastpos[u]);
            ret = max(ret,min(len[u] + 1,lastpos[u]-firstpos[u]));
        }
        if(ret<5) ret = 0;
        return ret;
    }
}sam;
void solve(){
    for(int i = 1; i <= n; i++) scanf("%d",&A[i]);
    for(int i = 1; i < n; i++) A[i] = A[i+1] - A[i] + 88;
    sam.init(); for(int i = 1; i < n; i++) sam.extend(A[i]);
    printf("%d
",sam.solve());
}
int main(){
    while(scanf("%d",&n)!=EOF and n) solve(); 
    return 0;
}

以上是关于POJ 1743 Musical ThemeSAM的主要内容,如果未能解决你的问题,请参考以下文章

poj 1743 Musical Theme

POJ 1743. Musical Theme

poj1743-----Musical Theme

POJ 1743Musical Theme

poj 1743 Musical Theme

poj 1743 Musical Theme(后缀数组)