zoukankan      html  css  js  c++  java
  • 最长公共子串2(LCS2) lg SP1812

    题意:n个字符串(n<=10)求最长公共子串的长度

    前置技能点:https://www.cnblogs.com/wenci/p/10432932.html (两个字符串求最长公共子串的长度)

    既然知道了两个串的最长公共子串怎么求

    那我们延伸一下,考虑两个变量,maxx表示在当前拿上来匹配得这个串在每个节点为终点时最长匹配的长度

    minn表示在之前所有串上匹配完,到当前节点最长匹配的长度

    先解释一下拓扑序的基数排序

    inline void radix_sort(){
        int i,j,k;
        for(i=1;i<=tot;i++){
            tong[node[i].len]++;
        }//开桶记录长度
        for(i=1;i<=tot;i++){
            tong[i]+=tong[i-1]; 
        }//表示当前长度能排到多少名
        for(i=1;i<=tot;i++){
            id[tong[node[i].len]--]=i;//重新排序后的数值
        } 
    }

    每一个串重新匹配的操作

    inline bool work(){
        if(scanf("%s",s)==EOF) return false;
        int p=1,len=0;int i,j,k;
        for(i=1;i<=tot;i++){
            node[i].maxx=0;
        }//把当前串的最大匹配清零
        int l1=strlen(s);
        for(i=0;i<l1;i++){
            int now=s[i]-'a'+1; 
            if(node[p].ch[now]){
                p=node[p].ch[now];len++;
            }
            else{
                while(p&&!node[p].ch[now]){
                    p=node[p].fa;
                }
                if(!p){
                    p=1;len=0;
                }
                else{
                    len=node[p].len+1;p=node[p].ch[now];
                }
            }//以上都和两个串匹配操作一样
            node[p].maxx=max(node[p].maxx,len);//这里更新一下当前串的最大匹配
        }
        for(i=tot;i;i--){//按照倒拓扑序,要优先修改儿子节点更新父亲节点
            int t=id[i];//基数排序后的序号
            node[t].minn=min(node[t].minn,node[t].maxx);//更新当前节点的最大匹配
            if(node[t].maxx>=node[t].len&&node[t].fa){//如果当前节点是满匹配的,那么删去结尾最后一个,也是满匹配的
                node[node[t].fa].maxx=node[node[t].fa].len;//把父亲节点的匹配也更新了
            }
        }
        return true;
    }

    最后贴整篇代码

    #include<bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    inline int read(){
        int w=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            w=(w<<3)+(w<<1)+ch-48;
            ch=getchar();
        }
        return w*f;
    }
    int n,m,lst=1,tot=1;
    long long size[2000010],sum[2000010];
    struct Node{
        int ch[30],len,fa,maxx,minn;
    }node[2000010];
    bool flag;
    inline void extend(int now){
        int p=lst;tot++;lst=tot;int np=tot;
        node[np].len=node[p].len+1;
        while(p&&!node[p].ch[now]){
            node[p].ch[now]=np;
            p=node[p].fa;
        }
        if(!p) node[np].fa = 1;
        else{
            int q = node[p].ch[now];
            if(node[q].len == node[p].len + 1){
                node[np].fa = q;
            }
            else{
                int nq=++tot;node[nq]=node[q];
                node[nq].len=node[p].len+1;
                node[np].fa=node[q].fa=nq;
                while(p&&node[p].ch[now] == q){
                    node[p].ch[now]=nq;
                    p=node[p].fa;
                }
            }
        }
    }
    int tong[2000010],id[2000010],ans;
    char s[2000010];
    inline void radix_sort(){
        int i,j,k;
        for(i=1;i<=tot;i++){
            tong[node[i].len]++;
        }
        for(i=1;i<=tot;i++){
            tong[i]+=tong[i-1]; 
        }
        for(i=1;i<=tot;i++){
            id[tong[node[i].len]--]=i;
        } 
    }
    inline bool work(){
        if(scanf("%s",s)==EOF) return false;
        int p=1,len=0;int i,j,k;
        for(i=1;i<=tot;i++){
            node[i].maxx=0;
        }
        int l1=strlen(s);
        for(i=0;i<l1;i++){
            int now=s[i]-'a'+1; 
            if(node[p].ch[now]){
                p=node[p].ch[now];len++;
            }
            else{
                while(p&&!node[p].ch[now]){
                    p=node[p].fa;
                }
                if(!p){
                    p=1;len=0;
                }
                else{
                    len=node[p].len+1;p=node[p].ch[now];
                }
            }
            node[p].maxx=max(node[p].maxx,len);
        }
        for(i=tot;i;i--){
            int t=id[i];
            node[t].minn=min(node[t].minn,node[t].maxx);
            if(node[t].maxx>=node[t].len&&node[t].fa){
                node[node[t].fa].maxx=node[node[t].fa].len;
            }
        }
        return true;
    }
    int main(){
        scanf("%s",s);int i,j,k;
        int l=strlen(s);
        for(i=0;i<=l;i++){
            extend(s[i]-'a'+1);
        }
        radix_sort();
        for(i=1;i<=tot;i++){
            node[i].minn=node[i].len;
        }
        while(work());
        for(i=1;i<=tot;i++){
            ans=max(ans,node[i].minn);
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    一网友推荐的书:框架设计(第2版):CLR Via C#
    线程与WinForm设计,防冻结,卡住窗体
    通用数据库操作辅助类DbHelper
    高级着色器语言(High Level Shader Language,简称HLSL)
    无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型
    根据RGB,计算灰度值
    温故而知新:WinForm/Silverlight多线程编程中如何更新UI控件的值
    [原创视频]PHP在netbeans中的简单使用
    自己封装的ASP.NET的SQLITE数据库的操作类
    《JavaScript征途》读后感
  • 原文地址:https://www.cnblogs.com/wenci/p/10433227.html
Copyright © 2011-2022 走看看