• 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;
    }
    
  • 相关阅读:
    Django搭建开发‘学习笔记’项目二(创建应用程序)
    Django搭建开发‘学习笔记’项目一(建立项目)
    WEB渗透 --- 常见问题总结
    ConstraintLayout使用手册
    Java源码分析(1):二分查找 + 循环递归实现
    小黄衫买家秀
    Android权限申请完全解析(一):Android自带的权限申请
    个人作业——软件工程实践总结作业
    beta阶段学习博客(一) js交互
    个人作业——软件产品案例分析
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12698595.html
Copyright © 2020-2023  润新知