• Codeforces 861D


    <题目链接>

    题目大意:

     输入7e4个长度为9的字符串,每个字符串中只出现0~9这几种数字,现在需要你输出每个母串中最短的特有子串。

    解题分析:

     利用Trie树进行公共子串的判定,因为Trie树的特性是对节点的前缀字符串进行操作,所以为了转换成对母串中任意区间的字符串进行操作,我们对母串中的所有后缀字符串建树。下面用了一个比较优秀的Trie树模板。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int N = 7e4+10;
     8 const int INF = 1e6;
     9 char buf[N][11];
    10 int n,cur;
    11 struct Trie{
    12     int nxt[N*11][12],num[N*11],time[N*11];     
    13     int root,pos;
    14     int newnode(){
    15         for(int i=0;i<10;i++)nxt[pos][i]=-1;
    16         num[pos]=0,time[pos]=0;
    17         return pos++;
    18     }
    19     void init(){
    20         pos=0;root=newnode();
    21     }
    22     void insert(char str[]){
    23         int len=strlen(str);
    24         int now=root;
    25         for(int i=0;i<len;i++){
    26             int to=str[i]-'0';
    27             if(nxt[now][to]==-1)
    28                 nxt[now][to]=newnode();
    29             now=nxt[now][to];
    30             if(time[now]!=cur)     //建立时间戳的意义是,避免相同母串中不同位置中的相同子串产生重复标记
    31                 num[now]++,time[now]=cur;      //num[now]记录下含有这个子串的母串数量
    32         }
    33     }
    34     int query(char str[]){
    35         int len=strlen(str);
    36         int now=root;
    37         for(int i=0;i<len;i++){
    38             now=nxt[now][str[i]-'0'];
    39             if(num[now]==1)return i;
    40         }
    41         return -1;
    42     }
    43 }trie;
    44 
    45 int main(){
    46     ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    47     cin>>n;
    48     trie.init();
    49     for(int i=1;i<=n;i++){
    50         cin>>buf[i];
    51         cur=i;
    52         for(int j=0;j<10;j++){
    53             trie.insert(buf[i]+j);     //用每个母串的所有后缀建Trie树,然后利用Trie树对前缀字符串进行操作的特性,达到对母串字符区间的操作
    54         }
    55     }
    56     for(int i=1;i<=n;i++){
    57         int le=0,ri=0,mn=INF;
    58         for(int j=0;j<10;j++){
    59             int tmp=trie.query(buf[i]+j);
    60             if(tmp!=-1 && mn>tmp){      //找到每个母串中符合条件的最短子串
    61                 mn=tmp;le=j,ri=j+tmp;
    62             }
    63         }
    64         for(int j=le;j<=ri;j++)cout<<buf[i][j];
    65         puts("");
    66     }
    67 }

    2019-02-01

  • 相关阅读:
    Oracle client 安装、配置
    js 计算金额是否小于总金额,大于是不能保存
    SQL Server函数与存储过程 计算时间
    sql Server 创建临时表 嵌套循环 添加数据
    SQL Server 事务日志文件已满,收缩日志文件(9002)
    sql Server 2008 数据库自动备份维护计划
    面向对象的三个基本特征:继承、封装、多肽
    MySQL 语句调优
    SQL 多表关联更新
    值类型、引用类型
  • 原文地址:https://www.cnblogs.com/00isok/p/10347200.html
Copyright © 2020-2023  润新知