zoukankan      html  css  js  c++  java
  • POJ2774 Long Long Message 【SAM】

    POJ2774 Long Long Message

    找两个串的最长公共字串
    对其中一个串(s)(SAM),然后我们如何找到最长公共字串,办法就是枚举(t)串所有的前缀,然后找各个前缀的最长能和(s)串匹配的后缀。
    如果一个个跑需要(O(n^2))(SAM)可以来保存之前匹配的状态,假设现在匹配的状态是(u),匹配到的最长后缀长度为(l),那么现在考虑在当前状态后面加上一个字符,也就是成为(t)串一个新的前缀,那么最大能匹配的必然是在上一次匹配到的最长串的基础上去匹配,所以我们可以不断判断(u)这个状态是否有连向新加入的字符的边,如果有的话,更新(u,l Rightarrow u = ch[u][c]; l+=1),如果没有的话,就要跑当前状态的后缀链接,找到最长的(endpos)不同的之前匹配串的一个后缀,然后更新(u,l Rightarrow u = link[u]; l = len[u]),直到遇到有连边的状态或者到了初始点。

    #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 = 2e5+7;
    char s[MAXN];
    struct SAM{
        int len[MAXN],link[MAXN],ch[MAXN][26],last,tot;
        void init(){ link[tot = last = 0] = -1; memset(ch[0],0,sizeof(ch[0])); }
        void extend(int c){
            int np = ++tot; memset(ch[tot],0,sizeof(ch[tot]));
            int p = last; len[np] = len[last] + 1;
            while(p!=-1 and !ch[p][c]){
                ch[p][c] = np;
                p = link[p];
            }
            if(p==-1) link[np] = 0;
            else{
                int q = ch[p][c];
                if(len[p]+1==len[q]) link[np] = q;
                else{
                    int clone = ++tot;
                    len[clone] = len[p] + 1;
                    link[clone] = link[q];
                    for(int i = 0; i < 26; i++) ch[clone][i] = ch[q][i];
                    link[np] = link[q] = clone;
                    while(p!=-1 and ch[p][c]==q){
                        ch[p][c] = clone;
                        p = link[p];
                    }
                }
            }
            last = np;
        }
        int lcs(char *str){
            int ret = 0, u = 0, l = 0, n = strlen(str);
            for(int i = 0; i < n; i++){
                int c = str[i] - 'a';
                while(u and !ch[u][c]){
                    u = link[u];
                    l = len[u];
                }
                if(ch[u][c]) u = ch[u][c], l++;
                ret = max(ret,l);
            }
            return ret;
        }
    }sam;
    int main(){
        while(scanf("%s",s)!=EOF){
            sam.init(); int n = strlen(s);
            for(int i = 0; i < n; i++) sam.extend(s[i]-'a');
            scanf("%s",s);
            printf("%d
    ",sam.lcs(s));
        }
        return 0;
    }
    
  • 相关阅读:
    STL源码剖析之_allocate函数
    PAT 1018. Public Bike Management
    PAT 1016. Phone Bills
    PAT 1012. The Best Rank
    PAT 1014. Waiting in Line
    PAT 1026. Table Tennis
    PAT 1017. Queueing at Bank
    STL源码剖析之list的sort函数实现
    吃到鸡蛋好吃,看看是哪只母鸡下的蛋:好用的Sqlite3
    cJSON
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12698595.html
Copyright © 2011-2022 走看看