zoukankan      html  css  js  c++  java
  • 【SAM】codevs3160-最长公共子串

    【题目大意】

    求两个字符串的最长公共子串。

    【思路】

    对第一个字符串建立后缀自动机,第二个字符串去匹配。cnt记录当前最长公共子串的长度,而ret记录答案。

    p代表位置指针,初始在rt位置。

    对于第二个字符串的某一位s[i],如果当前有s[i]孩子,则cnt+1,继续往后移动;否则沿着pre指针返回。如果pre指针返回到0,则将p回到rt,cnt清空为0;否则如果中间有点拥有s[i]孩子,cnt=step[]+1。

    为什么cnt=step[]+1?不要忘了后缀自动机的本质是维护后缀,沿着pre指针跑就是往长度更小的后缀移动,某位置代表的后缀的最长长度为step[],再加上s[i],即是step[]+1。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 const int MAXN=100000+5;
     8 int n;
     9 char str[2][MAXN];
    10 struct SAM
    11 {
    12     int step[MAXN*2],pre[MAXN*2],next[MAXN*2][26];
    13     int tot,last;
    14     inline int newNode(int cnt)
    15     {
    16         step[++tot]=cnt;
    17         pre[tot]=0;
    18         for (int i=0;i<26;i++) next[tot][i]=0;
    19         return tot;
    20     }
    21     
    22     inline void extend(int x)
    23     {
    24         int p=last;
    25         int np=newNode(step[p]+1);
    26         while (p && !next[p][x]) next[p][x]=np,p=pre[p];
    27         if (!p) pre[np]=1;
    28         else
    29         {
    30             int q=next[p][x];
    31             if (step[q]==step[p]+1) pre[np]=q;
    32             else 
    33             {
    34                 int nq=newNode(step[p]+1);
    35                 for (int i=0;i<26;i++) next[nq][i]=next[q][i];
    36                 pre[nq]=pre[q];
    37                 pre[q]=pre[np]=nq;
    38                 while (p&&next[p][x]==q) next[p][x]=nq,p=pre[p]; 
    39             }
    40     
    41         }
    42         last=np;
    43     }
    44     
    45     inline void clear()
    46     {
    47         int tot=0;
    48         last=newNode(tot);
    49     }
    50     
    51     inline int Query()
    52     {  
    53         int ret=0,cnt=0;  
    54         int p=1;  
    55         for(int i=0;str[1][i];i++)
    56         {  
    57             int index=str[1][i]-'a';
    58             if(next[p][index]) p=next[p][index],cnt++;
    59             else
    60             {    
    61                 while (p && !next[p][index]) p=pre[p];
    62                 if(!p) p=1,cnt=0;  
    63                     else cnt=step[p]+1,p=next[p][index];
    64                     /*由于沿着pre返回得到的字符串是当前字符串的后缀,所以第一个拥有index孩子的就是最长满足的后缀,长度即为step+1*/  
    65             }
    66             ret=max(ret,cnt);  
    67         }  
    68         return ret;  
    69     }  
    70 }suf;
    71 
    72 void init()
    73 {
    74     scanf("%d",&n);
    75     scanf("%s",str[0]);
    76     int len=strlen(str[0]);
    77     suf.clear();
    78     for (int i=0;i<len;i++) suf.extend(str[0][i]-'a');
    79     scanf("%s",str[1]);
    80 }
    81 
    82 int main()
    83 {
    84     init(); 
    85     printf("%d",suf.Query());
    86     return 0;
    87 } 
  • 相关阅读:
    字符串转XML保存后保证XML的格式
    SmartFoxServer学习(3)--第一个Extension
    SmartFoxServer学习(2)--Extension调试
    SmartFoxServer学习(1)--初步了解
    jmeter 开发自己的java请求 二次开发
    hive 面试题
    美丽说-爬虫记录
    python中re.sub的使用 --解读一段代码
    python 抓取美丽说店铺的宝贝图片及详细信息的实现(爬虫)
    hadoop编码问题,mapreduce中Tex与string的转化 乱码问题
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5743687.html
Copyright © 2011-2022 走看看