• SPOJ1811 LCS SAM


    后缀自动机简单题。

    其主要思路是,先对第一个字符串建立后缀自动机,把第二个串放在上面匹配,

    若当前状态s有字符x的转移,直接转移len=step+1。

    若当前状态s没有向字符x的转移,退回pres检查是否有转移,

    若没有,则继续退回,否则转移到节点y,len=stepy+1。

    以上思路主要利用的是关于pre节点的性质,由于pre节点的right集合是其子节点的right集合的并集,且max(pre)=min(s)-1.

    所以从pre节点往上跳的时候,就能找到最长的后缀相同的部分的节点。(不知道这么说对不对)。

    与KMP算法的很像。

    可以参考这篇博客

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<string>
     5 #include<cstring>
     6 #include<cmath>
     7 #include<ctime>
     8 #include<algorithm>
     9 #include<iomanip>
    10 #include<set>
    11 #include<map>
    12 #include<queue>
    13 using namespace std;
    14 #define mem1(i,j) memset(i,j,sizeof(i))
    15 #define mem2(i,j) memcpy(i,j,sizeof(i))
    16 #define LL long long
    17 #define up(i,j,n) for(int i=(j);i<=(n);i++)
    18 #define FILE "dealing"
    19 #define poi vec
    20 #define eps 1e-10
    21 #define db double 
    22 const int maxn=250100,inf=1000000000,mod=1000000007;
    23 int read(){
    24     int x=0,f=1,ch=getchar();
    25     while(x<'0'||x>'9'){if(ch=='-')f=-1;ch=getchar();}
    26     while(x<='9'&&x>='0'){x=(x<<1)+(x<<3)+ch-'0',ch=getchar();}
    27     return f*x;
    28 }
    29 bool cmax(int& a,int b){return a<b?a=b,true:false;}
    30 namespace sam{
    31     const int maxn=505000;
    32     int pre[maxn],c[maxn][26],len[maxn],now,cnt,np,p,q,nq,Len;
    33     void clear(){mem1(c,0);mem1(len,0);mem1(pre,0);cnt=1,now=1;}
    34     void expend(int x){
    35         np=++cnt;len[np]=len[now]+1;p=now;now=np;
    36         while(p&&!c[p][x])c[p][x]=np,p=pre[p];
    37         if(!p)pre[np]=1;
    38         else {
    39             q=c[p][x];
    40             if(len[q]==len[p]+1)pre[np]=q;
    41             else {
    42                 len[nq=++cnt]=len[p]+1;
    43                 pre[nq]=pre[q];
    44                 pre[q]=pre[np]=nq;
    45                 mem2(c[nq],c[q]);
    46                 while(p&&c[p][x]==q)c[p][x]=nq,p=pre[p];
    47             }
    48         }
    49     }
    50     int walk(int x){
    51         while(!c[now][x]&&pre[now])now=pre[now],Len=len[now];
    52         if(!c[now][x])return 0;
    53         now=c[now][x];Len++;return Len;
    54     }
    55     void build(char* s){
    56         int n=strlen(s+1);
    57         up(i,1,n)expend(s[i]-'a');
    58     }
    59 };
    60 char s[maxn];
    61 int main(){
    62     freopen(FILE".in","r",stdin);
    63     freopen(FILE".out","w",stdout);
    64     sam::clear();
    65     scanf("%s",s+1);
    66     sam::build(s);
    67     scanf("%s",s+1);
    68     int n=strlen(s+1);
    69     int ans=0;sam::now=1;sam::Len=0;
    70     up(i,1,n)cmax(ans,sam::walk(s[i]-'a'));
    71     cout<<ans<<endl;
    72     return 0;
    73 }
    View Code
  • 相关阅读:
    VC combobox
    myitoa()函数
    什么是虚拟显示
    一些itoa()函数
    C语言运算符优先级
    一些小问题
    return 语句会发生的错误
    Sizeof与Strlen的区别与联系
    用异或运算符实现不用第三个临时变量交换两个变量的值
    字符串化运算符#
  • 原文地址:https://www.cnblogs.com/chadinblog/p/6419178.html
Copyright © 2020-2023  润新知