• 最长公共子串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;
    }
  • 相关阅读:
    mssql:tsql;创建表;给表添加约束;使用变量;事务,索引,视图;存储过程;触发器trigger;播放器http://www.smartgz.com/blog/Article/956.asp
    str.Replace(" ","");
    DataGrid分页;指定列的总和和平均值;显示鼠标背景色;弹出式窗口;
    .net 面试题 (1)
    数据绑定技术_单值数据绑定示例;将 DataTable,DataSet,DataView,DataReader 绑定到 DataGrid 控件示例;DataBinder.Eval;数组的值赋给ListBox1;Hashtable 绑定到;RadioButtonList;将XML 文件做为数据源绑定到控件
    Lession 17 Always young 保持年轻
    智力面试题
    Lession 16 A Polite request 彬彬有礼的要求
    几道 C 语言面试题
    建表的范例脚本,存储过程中参数的命名
  • 原文地址:https://www.cnblogs.com/wenci/p/10433227.html
Copyright © 2020-2023  润新知